Skip to content

Commit cb9ecbc

Browse files
sstricklCommit Queue
authored andcommitted
[vm] Enforce that entry points must be annotated by default.
Changes the default value of the --verify-entry-points flag to true. Changes the default value for the check_is_entrypoint argument to to the Invoke/InvokeGetter/InvokeSetter flags to true. The mirrors library implementation and calls via vm-service explicitly pass false for this argument now. Add annotations as needed, such as annotating classes with annotated generative constructors. In some cases, the annotations were more general than needed (e.g., annotating with a no-argument entry point annotation when only the setter is needed), so make those annotations more specific. As this pattern is already common in downstream code, allow Dart_Invoke on fields as long as the field is annotated for getter access. (That is, calling Dart_Invoke for a field is equivalent to retrieving the closure value via Dart_GetField and then calling Dart_InvokeClosure.) TEST=vm/cc/DartAPI_MissingEntryPoints vm/dart/entrypoints_verification_test Issue: #50649 Issue: flutter/flutter#118608 Change-Id: Ibb3bf15632ab2958d8791b449af8651d47f871a5 Cq-Include-Trybots: luci.dart.try:vm-aot-linux-product-x64-try,vm-aot-linux-debug-x64-try,vm-aot-mac-release-arm64-try,vm-aot-mac-product-arm64-try,vm-aot-dwarf-linux-product-x64-try CoreLibraryReviewExempt: adding/editing vm-only pragma annotations Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/363566 Reviewed-by: Martin Kustermann <[email protected]> Commit-Queue: Tess Strickland <[email protected]>
1 parent b3385ba commit cb9ecbc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1195
-651
lines changed

runtime/bin/entrypoints_verification_test.cc

Lines changed: 188 additions & 97 deletions
Large diffs are not rendered by default.

runtime/docs/compiler/aot/entry_point_pragma.md

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ The annotation `@pragma("vm:entry-point", ...)` **must** be placed on a class or
44
member to indicate that it may be resolved, allocated or invoked directly from
55
native or VM code _in AOT mode_.
66

7+
To reduce the differences between JIT and AOT mode, entry point annotations are
8+
also checked in JIT mode except for uses of the `dart:mirrors` library and
9+
debugging uses via the VM service.
10+
711
## Background
812

913
Dart VM precompiler (AOT compiler) performs whole-program optimizations such as
@@ -88,11 +92,14 @@ three forms may be attached to static fields.
8892
int foo;
8993
```
9094

91-
If the second parameter is missing, `null` or `true, the field is marked for
95+
If the second parameter is missing, `null` or `true`, the field is marked for
9296
native access and for non-static fields the corresponding getter and setter in
9397
the interface of the enclosing class are marked for native invocation. If the
94-
'get'/'set' parameter is used, only the getter/setter is marked. For static
95-
fields, the implicit getter is always marked. The third form does not make sense
96-
for static fields because they do not belong to an interface.
97-
98-
Note that no form of entry-point annotation allows invoking a field.
98+
"get" or "set" parameter is used, only the getter or setter is marked. For
99+
static fields, the implicit getter is always marked if the field is marked
100+
for native access.
101+
102+
A field containing a closure may only be invoked using Dart_Invoke if the
103+
getter is marked, in which case it is the same as retrieving the closure from
104+
the field using Dart_GetField and then invoking the closure using
105+
Dart_InvokeClosure.

runtime/lib/isolate.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -714,7 +714,7 @@ ObjectPtr IsolateSpawnState::ResolveFunction() {
714714
// Check whether the root library defines a main function.
715715
const Library& lib =
716716
Library::Handle(zone, IG->object_store()->root_library());
717-
const String& main = String::Handle(zone, String::New("main"));
717+
const String& main = Symbols::main();
718718
Function& func = Function::Handle(zone, lib.LookupFunctionAllowPrivate(main));
719719
if (func.IsNull()) {
720720
// Check whether main is reexported from the root library.

runtime/lib/mirrors.cc

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1221,6 +1221,8 @@ DEFINE_NATIVE_ENTRY(TypeVariableMirror_upper_bound, 0, 1) {
12211221
return param.bound();
12221222
}
12231223

1224+
static constexpr bool kNoStrictEntryPointChecks = false;
1225+
12241226
DEFINE_NATIVE_ENTRY(InstanceMirror_invoke, 0, 5) {
12251227
// Argument 0 is the mirror, which is unused by the native. It exists
12261228
// because this native is an instance method in order to be polymorphic
@@ -1230,7 +1232,8 @@ DEFINE_NATIVE_ENTRY(InstanceMirror_invoke, 0, 5) {
12301232
arguments->NativeArgAt(2));
12311233
GET_NON_NULL_NATIVE_ARGUMENT(Array, args, arguments->NativeArgAt(3));
12321234
GET_NON_NULL_NATIVE_ARGUMENT(Array, arg_names, arguments->NativeArgAt(4));
1233-
RETURN_OR_PROPAGATE(reflectee.Invoke(function_name, args, arg_names));
1235+
RETURN_OR_PROPAGATE(reflectee.Invoke(function_name, args, arg_names,
1236+
kNoStrictEntryPointChecks));
12341237
}
12351238

12361239
DEFINE_NATIVE_ENTRY(InstanceMirror_invokeGetter, 0, 3) {
@@ -1239,7 +1242,8 @@ DEFINE_NATIVE_ENTRY(InstanceMirror_invokeGetter, 0, 3) {
12391242
// with its cousins.
12401243
GET_NATIVE_ARGUMENT(Instance, reflectee, arguments->NativeArgAt(1));
12411244
GET_NON_NULL_NATIVE_ARGUMENT(String, getter_name, arguments->NativeArgAt(2));
1242-
RETURN_OR_PROPAGATE(reflectee.InvokeGetter(getter_name));
1245+
RETURN_OR_PROPAGATE(
1246+
reflectee.InvokeGetter(getter_name, kNoStrictEntryPointChecks));
12431247
}
12441248

12451249
DEFINE_NATIVE_ENTRY(InstanceMirror_invokeSetter, 0, 4) {
@@ -1249,7 +1253,8 @@ DEFINE_NATIVE_ENTRY(InstanceMirror_invokeSetter, 0, 4) {
12491253
GET_NATIVE_ARGUMENT(Instance, reflectee, arguments->NativeArgAt(1));
12501254
GET_NON_NULL_NATIVE_ARGUMENT(String, setter_name, arguments->NativeArgAt(2));
12511255
GET_NATIVE_ARGUMENT(Instance, value, arguments->NativeArgAt(3));
1252-
RETURN_OR_PROPAGATE(reflectee.InvokeSetter(setter_name, value));
1256+
RETURN_OR_PROPAGATE(
1257+
reflectee.InvokeSetter(setter_name, value, kNoStrictEntryPointChecks));
12531258
}
12541259

12551260
DEFINE_NATIVE_ENTRY(InstanceMirror_computeType, 0, 1) {
@@ -1309,7 +1314,8 @@ DEFINE_NATIVE_ENTRY(ClassMirror_invoke, 0, 5) {
13091314
arguments->NativeArgAt(2));
13101315
GET_NON_NULL_NATIVE_ARGUMENT(Array, args, arguments->NativeArgAt(3));
13111316
GET_NON_NULL_NATIVE_ARGUMENT(Array, arg_names, arguments->NativeArgAt(4));
1312-
RETURN_OR_PROPAGATE(klass.Invoke(function_name, args, arg_names));
1317+
RETURN_OR_PROPAGATE(
1318+
klass.Invoke(function_name, args, arg_names, kNoStrictEntryPointChecks));
13131319
}
13141320

13151321
DEFINE_NATIVE_ENTRY(ClassMirror_invokeGetter, 0, 3) {
@@ -1324,7 +1330,8 @@ DEFINE_NATIVE_ENTRY(ClassMirror_invokeGetter, 0, 3) {
13241330
UNREACHABLE();
13251331
}
13261332
GET_NON_NULL_NATIVE_ARGUMENT(String, getter_name, arguments->NativeArgAt(2));
1327-
RETURN_OR_PROPAGATE(klass.InvokeGetter(getter_name, true));
1333+
RETURN_OR_PROPAGATE(
1334+
klass.InvokeGetter(getter_name, kNoStrictEntryPointChecks));
13281335
}
13291336

13301337
DEFINE_NATIVE_ENTRY(ClassMirror_invokeSetter, 0, 4) {
@@ -1335,7 +1342,8 @@ DEFINE_NATIVE_ENTRY(ClassMirror_invokeSetter, 0, 4) {
13351342
const Class& klass = Class::Handle(ref.GetClassReferent());
13361343
GET_NON_NULL_NATIVE_ARGUMENT(String, setter_name, arguments->NativeArgAt(2));
13371344
GET_NATIVE_ARGUMENT(Instance, value, arguments->NativeArgAt(3));
1338-
RETURN_OR_PROPAGATE(klass.InvokeSetter(setter_name, value));
1345+
RETURN_OR_PROPAGATE(
1346+
klass.InvokeSetter(setter_name, value, kNoStrictEntryPointChecks));
13391347
}
13401348

13411349
DEFINE_NATIVE_ENTRY(ClassMirror_invokeConstructor, 0, 5) {
@@ -1488,7 +1496,8 @@ DEFINE_NATIVE_ENTRY(LibraryMirror_invoke, 0, 5) {
14881496
arguments->NativeArgAt(2));
14891497
GET_NON_NULL_NATIVE_ARGUMENT(Array, args, arguments->NativeArgAt(3));
14901498
GET_NON_NULL_NATIVE_ARGUMENT(Array, arg_names, arguments->NativeArgAt(4));
1491-
RETURN_OR_PROPAGATE(library.Invoke(function_name, args, arg_names));
1499+
RETURN_OR_PROPAGATE(library.Invoke(function_name, args, arg_names,
1500+
kNoStrictEntryPointChecks));
14921501
}
14931502

14941503
DEFINE_NATIVE_ENTRY(LibraryMirror_invokeGetter, 0, 3) {
@@ -1498,7 +1507,8 @@ DEFINE_NATIVE_ENTRY(LibraryMirror_invokeGetter, 0, 3) {
14981507
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
14991508
const Library& library = Library::Handle(ref.GetLibraryReferent());
15001509
GET_NON_NULL_NATIVE_ARGUMENT(String, getter_name, arguments->NativeArgAt(2));
1501-
RETURN_OR_PROPAGATE(library.InvokeGetter(getter_name, true));
1510+
RETURN_OR_PROPAGATE(
1511+
library.InvokeGetter(getter_name, kNoStrictEntryPointChecks));
15021512
}
15031513

15041514
DEFINE_NATIVE_ENTRY(LibraryMirror_invokeSetter, 0, 4) {
@@ -1509,7 +1519,8 @@ DEFINE_NATIVE_ENTRY(LibraryMirror_invokeSetter, 0, 4) {
15091519
const Library& library = Library::Handle(ref.GetLibraryReferent());
15101520
GET_NON_NULL_NATIVE_ARGUMENT(String, setter_name, arguments->NativeArgAt(2));
15111521
GET_NATIVE_ARGUMENT(Instance, value, arguments->NativeArgAt(3));
1512-
RETURN_OR_PROPAGATE(library.InvokeSetter(setter_name, value));
1522+
RETURN_OR_PROPAGATE(
1523+
library.InvokeSetter(setter_name, value, kNoStrictEntryPointChecks));
15131524
}
15141525

15151526
DEFINE_NATIVE_ENTRY(MethodMirror_owner, 0, 2) {

runtime/tests/vm/dart/entrypoints_verification_test.dart

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,20 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44
//
5-
// VMOptions=--verify-entry-points=true
65
// SharedObjects=entrypoints_verification_test
76

87
import 'dart:ffi';
98
import './dylib_utils.dart';
109

11-
main() {
10+
main(List<String> args) {
1211
final helper = dlopenPlatformSpecific('entrypoints_verification_test');
1312
final runTest =
1413
helper.lookupFunction<Void Function(), void Function()>('RunTests');
1514
runTest();
16-
17-
new C();
18-
new D();
1915
}
2016

17+
final void Function() noop = () {};
18+
2119
class C {}
2220

2321
@pragma("vm:entry-point")
@@ -52,16 +50,16 @@ class D {
5250
@pragma("vm:entry-point", "get")
5351
static void fn3_get() {}
5452

55-
void Function()? fld0;
53+
void Function()? fld0 = noop;
5654

5755
@pragma("vm:entry-point")
58-
void Function()? fld1;
56+
void Function()? fld1 = noop;
5957

6058
@pragma("vm:entry-point", "get")
61-
void Function()? fld2;
59+
void Function()? fld2 = noop;
6260

6361
@pragma("vm:entry-point", "set")
64-
void Function()? fld3;
62+
void Function()? fld3 = noop;
6563
}
6664

6765
void fn0() {}
@@ -81,25 +79,25 @@ class E extends D {
8179

8280
@pragma("vm:entry-point")
8381
class F {
84-
static void Function()? fld0;
82+
static void Function()? fld0 = noop;
8583

8684
@pragma("vm:entry-point")
87-
static void Function()? fld1;
85+
static void Function()? fld1 = noop;
8886

8987
@pragma("vm:entry-point", "get")
90-
static void Function()? fld2;
88+
static void Function()? fld2 = noop;
9189

9290
@pragma("vm:entry-point", "set")
93-
static void Function()? fld3;
91+
static void Function()? fld3 = noop;
9492
}
9593

96-
void Function()? fld0;
94+
void Function()? fld0 = noop;
9795

9896
@pragma("vm:entry-point")
99-
void Function()? fld1;
97+
void Function()? fld1 = noop;
10098

10199
@pragma("vm:entry-point", "get")
102-
void Function()? fld2;
100+
void Function()? fld2 = noop;
103101

104102
@pragma("vm:entry-point", "set")
105-
void Function()? fld3;
103+
void Function()? fld3 = noop;

runtime/vm/benchmark_test.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ base class Class extends NativeFieldWrapperClass1 {
176176
external int method(int param1, int param2);
177177
}
178178
179+
@pragma('vm:entry-point', 'call')
179180
void benchmark(int count) {
180181
Class c = Class();
181182
c.init();
@@ -336,7 +337,9 @@ BENCHMARK(FrameLookup) {
336337
return StackFrame.accessFrame();
337338
}
338339
}
340+
@pragma('vm:entry-point')
339341
class StackFrameTest {
342+
@pragma('vm:entry-point', 'call')
340343
static int testMain() {
341344
First obj = new First();
342345
return obj.method1(1);
@@ -430,6 +433,7 @@ BENCHMARK(CreateMirrorSystem) {
430433
const char* kScriptChars =
431434
"import 'dart:mirrors';\n"
432435
"\n"
436+
"@pragma('vm:entry-point', 'call')\n"
433437
"void benchmark() {\n"
434438
" currentMirrorSystem();\n"
435439
"}\n";
@@ -535,6 +539,7 @@ BENCHMARK(SimpleMessage) {
535539

536540
BENCHMARK(LargeMap) {
537541
const char* kScript =
542+
"@pragma('vm:entry-point', 'call')\n"
538543
"makeMap() {\n"
539544
" Map m = {};\n"
540545
" for (int i = 0; i < 100000; ++i) m[i*13+i*(i>>7)] = i;\n"

runtime/vm/compiler/aot/precompiler.cc

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -738,7 +738,7 @@ void Precompiler::AddRoots() {
738738
UNREACHABLE();
739739
}
740740

741-
const String& name = String::Handle(String::New("main"));
741+
const String& name = Symbols::main();
742742
Function& main = Function::Handle(lib.LookupFunctionAllowPrivate(name));
743743
if (main.IsNull()) {
744744
const Object& obj = Object::Handle(lib.LookupReExport(name));
@@ -1381,20 +1381,10 @@ const char* Precompiler::MustRetainFunction(const Function& function) {
13811381
// * Native functions (for LinkNativeCall)
13821382
// * Selector matches a symbol used in Resolver::ResolveDynamic calls
13831383
// in dart_entry.cc or dart_api_impl.cc.
1384-
// * _Closure.call (used in async stack handling)
13851384
if (function.is_old_native()) {
13861385
return "native function";
13871386
}
13881387

1389-
// Use the same check for _Closure.call as in stack_trace.{h|cc}.
1390-
const auto& selector = String::Handle(Z, function.name());
1391-
if (selector.ptr() == Symbols::call().ptr()) {
1392-
const auto& name = String::Handle(Z, function.QualifiedScrubbedName());
1393-
if (name.Equals(Symbols::_ClosureCall())) {
1394-
return "_Closure.call";
1395-
}
1396-
}
1397-
13981388
// We have to retain functions which can be a target of a SwitchableCall
13991389
// at AOT runtime, since the AOT runtime needs to be able to find the
14001390
// function object in the class.

runtime/vm/compiler/backend/il_test_helper.cc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,15 @@ TypeParameterPtr GetFunctionTypeParameter(const Function& fun, intptr_t index) {
8181
return param.ptr();
8282
}
8383

84-
ObjectPtr Invoke(const Library& lib, const char* name) {
84+
ObjectPtr Invoke(const Library& lib,
85+
const char* name,
86+
bool check_is_entrypoint) {
8587
Thread* thread = Thread::Current();
8688
Dart_Handle api_lib = Api::NewHandle(thread, lib.ptr());
8789
Dart_Handle result;
8890
{
8991
TransitionVMToNative transition(thread);
92+
SetFlagScope<bool> sfs(&FLAG_verify_entry_points, check_is_entrypoint);
9093
result =
9194
Dart_Invoke(api_lib, NewString(name), /*argc=*/0, /*argv=*/nullptr);
9295
EXPECT_VALID(result);

runtime/vm/compiler/backend/il_test_helper.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,9 @@ ClassPtr GetClass(const Library& lib, const char* name);
6565
TypeParameterPtr GetClassTypeParameter(const Class& klass, intptr_t index);
6666
TypeParameterPtr GetFunctionTypeParameter(const Function& fun, intptr_t index);
6767

68-
ObjectPtr Invoke(const Library& lib, const char* name);
68+
ObjectPtr Invoke(const Library& lib,
69+
const char* name,
70+
bool check_is_entrypoint = false);
6971

7072
InstructionsPtr BuildInstructions(
7173
std::function<void(compiler::Assembler* assembler)> fun);

runtime/vm/compiler/backend/inliner_test.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,7 +580,9 @@ external InspectStack();
580580
@pragma('vm:never-inline')
581581
void nop() {}
582582
583+
@pragma('vm:entry-point', 'get')
583584
int prologueCount = 0;
585+
@pragma('vm:entry-point', 'get')
584586
int epilogueCount = 0;
585587
586588
@pragma('vm:never-inline')

0 commit comments

Comments
 (0)