Skip to content

Commit 9b06e26

Browse files
sstricklCommit Queue
authored and
Commit Queue
committed
Reland "[vm] Enforce that entry points must be annotated by default."
This is a reland of commit cb9ecbc This reland only turns on the entry point verification flag by default in AOT mode. After Flutter tests that use native access in JIT mode have been appropriately updated, a followup CL will turn this flag on by default in JIT mode as well. Original change's description: > [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]> TEST=vm/cc/DartAPI_MissingEntryPoints vm/dart/entrypoints_verification_test Change-Id: I24919c32ab4760c7c5435c378879791086256f02 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,flutter-linux-try,vm-linux-debug-x64-try,vm-linux-release-x64-try,vm-appjit-linux-product-x64-try CoreLibraryReviewExempt: adding/editing vm-only pragma annotations Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/391620 Reviewed-by: Martin Kustermann <[email protected]> Commit-Queue: Tess Strickland <[email protected]>
1 parent 805935d commit 9b06e26

Some content is hidden

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

44 files changed

+1214
-664
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
@@ -710,7 +710,7 @@ ObjectPtr IsolateSpawnState::ResolveFunction() {
710710
// Check whether the root library defines a main function.
711711
const Library& lib =
712712
Library::Handle(zone, IG->object_store()->root_library());
713-
const String& main = String::Handle(zone, String::New("main"));
713+
const String& main = Symbols::main();
714714
Function& func = Function::Handle(zone, lib.LookupFunctionAllowPrivate(main));
715715
if (func.IsNull()) {
716716
// 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 & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,15 @@
88
import 'dart:ffi';
99
import './dylib_utils.dart';
1010

11-
main() {
11+
main(List<String> args) {
1212
final helper = dlopenPlatformSpecific('entrypoints_verification_test');
1313
final runTest =
1414
helper.lookupFunction<Void Function(), void Function()>('RunTests');
1515
runTest();
16-
17-
new C();
18-
new D();
1916
}
2017

18+
final void Function() noop = () {};
19+
2120
class C {}
2221

2322
@pragma("vm:entry-point")
@@ -52,16 +51,16 @@ class D {
5251
@pragma("vm:entry-point", "get")
5352
static void fn3_get() {}
5453

55-
void Function()? fld0;
54+
void Function()? fld0 = noop;
5655

5756
@pragma("vm:entry-point")
58-
void Function()? fld1;
57+
void Function()? fld1 = noop;
5958

6059
@pragma("vm:entry-point", "get")
61-
void Function()? fld2;
60+
void Function()? fld2 = noop;
6261

6362
@pragma("vm:entry-point", "set")
64-
void Function()? fld3;
63+
void Function()? fld3 = noop;
6564
}
6665

6766
void fn0() {}
@@ -81,25 +80,25 @@ class E extends D {
8180

8281
@pragma("vm:entry-point")
8382
class F {
84-
static void Function()? fld0;
83+
static void Function()? fld0 = noop;
8584

8685
@pragma("vm:entry-point")
87-
static void Function()? fld1;
86+
static void Function()? fld1 = noop;
8887

8988
@pragma("vm:entry-point", "get")
90-
static void Function()? fld2;
89+
static void Function()? fld2 = noop;
9190

9291
@pragma("vm:entry-point", "set")
93-
static void Function()? fld3;
92+
static void Function()? fld3 = noop;
9493
}
9594

96-
void Function()? fld0;
95+
void Function()? fld0 = noop;
9796

9897
@pragma("vm:entry-point")
99-
void Function()? fld1;
98+
void Function()? fld1 = noop;
10099

101100
@pragma("vm:entry-point", "get")
102-
void Function()? fld2;
101+
void Function()? fld2 = noop;
103102

104103
@pragma("vm:entry-point", "set")
105-
void Function()? fld3;
104+
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
@@ -740,7 +740,7 @@ void Precompiler::AddRoots() {
740740
UNREACHABLE();
741741
}
742742

743-
const String& name = String::Handle(String::New("main"));
743+
const String& name = Symbols::main();
744744
Function& main = Function::Handle(lib.LookupFunctionAllowPrivate(name));
745745
if (main.IsNull()) {
746746
const Object& obj = Object::Handle(lib.LookupReExport(name));
@@ -1383,20 +1383,10 @@ const char* Precompiler::MustRetainFunction(const Function& function) {
13831383
// * Native functions (for LinkNativeCall)
13841384
// * Selector matches a symbol used in Resolver::ResolveDynamic calls
13851385
// in dart_entry.cc or dart_api_impl.cc.
1386-
// * _Closure.call (used in async stack handling)
13871386
if (function.is_old_native()) {
13881387
return "native function";
13891388
}
13901389

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

runtime/vm/compiler/backend/il_test_helper.cc

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -81,19 +81,6 @@ TypeParameterPtr GetFunctionTypeParameter(const Function& fun, intptr_t index) {
8181
return param.ptr();
8282
}
8383

84-
ObjectPtr Invoke(const Library& lib, const char* name) {
85-
Thread* thread = Thread::Current();
86-
Dart_Handle api_lib = Api::NewHandle(thread, lib.ptr());
87-
Dart_Handle result;
88-
{
89-
TransitionVMToNative transition(thread);
90-
result =
91-
Dart_Invoke(api_lib, NewString(name), /*argc=*/0, /*argv=*/nullptr);
92-
EXPECT_VALID(result);
93-
}
94-
return Api::UnwrapHandle(result);
95-
}
96-
9784
InstructionsPtr BuildInstructions(
9885
std::function<void(compiler::Assembler* assembler)> fun) {
9986
auto thread = Thread::Current();

runtime/vm/compiler/backend/il_test_helper.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,6 @@ 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);
69-
7068
InstructionsPtr BuildInstructions(
7169
std::function<void(compiler::Assembler* assembler)> fun);
7270

runtime/vm/compiler/backend/inliner_test.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,9 @@ external InspectStack();
581581
@pragma('vm:never-inline')
582582
void nop() {}
583583
584+
@pragma('vm:entry-point', 'get')
584585
int prologueCount = 0;
586+
@pragma('vm:entry-point', 'get')
585587
int epilogueCount = 0;
586588
587589
@pragma('vm:never-inline')

runtime/vm/compiler/backend/redundancy_elimination_test.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1937,6 +1937,7 @@ ISOLATE_UNIT_TEST_CASE(Ffi_StructSinking) {
19371937
external int a;
19381938
}
19391939
1940+
@pragma('vm:entry-point')
19401941
int test(int addr) =>
19411942
Pointer<S>.fromAddress(addr)[0].a;
19421943
)";

runtime/vm/compiler_test.cc

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -176,13 +176,16 @@ ISOLATE_UNIT_TEST_CASE(RegenerateAllocStubs) {
176176

177177
TEST_CASE(EvalExpression) {
178178
const char* kScriptChars =
179-
"int ten = 2 * 5; \n"
180-
"get dot => '.'; \n"
181-
"class A { \n"
182-
" var apa = 'Herr Nilsson'; \n"
183-
" calc(x) => '${x*ten}'; \n"
184-
"} \n"
185-
"makeObj() => new A(); \n";
179+
R"(
180+
int ten = 2 * 5;
181+
get dot => '.';
182+
class A {
183+
var apa = 'Herr Nilsson';
184+
calc(x) => '${x*ten}';
185+
}
186+
@pragma('vm:entry-point', 'call')
187+
makeObj() => new A();
188+
)";
186189

187190
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
188191
Dart_Handle obj_handle =

runtime/vm/custom_isolate_test.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ static const char* kCustomIsolateScriptChars =
2929
import 'dart:isolate';
3030
3131
final RawReceivePort mainPort = new RawReceivePort();
32+
@pragma('vm:entry-point', 'get')
3233
final SendPort mainSendPort = mainPort.sendPort;
3334
3435
@pragma('vm:external-name', 'native_echo')
@@ -55,6 +56,7 @@ static const char* kCustomIsolateScriptChars =
5556
SendPort spawn();
5657
}
5758
59+
@pragma('vm:entry-point', 'call')
5860
isolateMain() {
5961
echo('Running isolateMain');
6062
mainPort.handler = (message) {

0 commit comments

Comments
 (0)