Skip to content

Commit

Permalink
Account for @pragma("vm:entry-point") creating additional "root" libr…
Browse files Browse the repository at this point in the history
…aries when partitioning the program into loading units.

If a library contained an entry point but was not reachable from the root library, it was not assigned to any loading unit and caused a null dereference in gen_snapshot. This is not possible with the standalone embedder, but is possible in Flutter because it passes multiple sources to frontend_server.  E.g., `--source dart_plugin_registrant.dart`.

TEST=gallery
Bug: flutter/gallery#545
Change-Id: I9c67f0e39f7509094ee873610d80851a702a0cf2
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/249640
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
  • Loading branch information
rmacnak-google authored and Commit Bot committed Jun 23, 2022
1 parent 9395116 commit 9c2a91f
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 8 deletions.
2 changes: 1 addition & 1 deletion pkg/vm/lib/kernel_front_end.dart
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ Future runGlobalTransformations(
// it does it will need the obfuscation prohibitions.
obfuscationProhibitions.transformComponent(component, coreTypes, target);

deferred_loading.transformComponent(component);
deferred_loading.transformComponent(component, coreTypes, target);
}

/// Runs given [action] with [CompilerContext]. This is needed to
Expand Down
60 changes: 54 additions & 6 deletions pkg/vm/lib/transformations/deferred_loading.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@
library vm.transformations.deferred_loading;

import 'package:kernel/ast.dart';
import 'package:kernel/core_types.dart' show CoreTypes;
import 'package:kernel/target/targets.dart' show Target;

import '../dominators.dart';
import '../metadata/loading_units.dart';
import 'pragma.dart';

class _LoadingUnitBuilder {
late int id;
Expand Down Expand Up @@ -37,7 +41,42 @@ class _LibraryVertex extends Vertex<_LibraryVertex> {
String toString() => "_LibraryVertex(${library.importUri})";
}

List<LoadingUnit> computeLoadingUnits(Component component) {
class HasEntryPointVisitor extends RecursiveVisitor {
final PragmaAnnotationParser parser;
bool _hasEntryPoint = false;

HasEntryPointVisitor(this.parser);

visitAnnotations(List<Expression> annotations) {
for (var ann in annotations) {
ParsedPragma? pragma = parser.parsePragma(ann);
if (pragma is ParsedEntryPointPragma) {
_hasEntryPoint = true;
return;
}
}
}

@override
visitClass(Class klass) {
visitAnnotations(klass.annotations);
klass.visitChildren(this);
}

@override
defaultMember(Member node) {
visitAnnotations(node.annotations);
}

bool hasEntryPoint(Library lib) {
_hasEntryPoint = false;
visitLibrary(lib);
return _hasEntryPoint;
}
}

List<LoadingUnit> computeLoadingUnits(
Component component, HasEntryPointVisitor visitor) {
// 1. Build the dominator tree for the library import graph.
final map = <Library, _LibraryVertex>{};
for (final lib in component.libraries) {
Expand All @@ -51,10 +90,15 @@ List<LoadingUnit> computeLoadingUnits(Component component) {
}
final root = map[component.mainMethod!.enclosingLibrary]!;

// Fake imports from root library to every core library so they end up in
// the same loading unit attributed to the user's root library.
// Fake imports from root library to every core library or library containing
// an entry point pragma so that they end up in the same loading unit
// attributed to the user's root library.
for (final vertex in map.values) {
if (vertex.library.importUri.isScheme("dart")) {
if (vertex == root) {
continue;
}
if (vertex.library.importUri.isScheme("dart") ||
visitor.hasEntryPoint(vertex.library)) {
root.successors.add(vertex);
vertex.isLoadingRoot = false;
}
Expand Down Expand Up @@ -127,8 +171,12 @@ List<LoadingUnit> computeLoadingUnits(Component component) {
return loadingUnits.map((u) => u.asLoadingUnit()).toList();
}

Component transformComponent(Component component) {
final metadata = new LoadingUnitsMetadata(computeLoadingUnits(component));
Component transformComponent(
Component component, CoreTypes coreTypes, Target target) {
final parser = ConstantPragmaAnnotationParser(coreTypes, target);
final visitor = HasEntryPointVisitor(parser);
final metadata =
new LoadingUnitsMetadata(computeLoadingUnits(component, visitor));
final repo = new LoadingUnitsMetadataRepository();
component.addMetadataRepository(repo);
repo.mapping[component] = metadata;
Expand Down
5 changes: 4 additions & 1 deletion pkg/vm/test/transformations/deferred_loading_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'dart:io';

import 'package:kernel/target/targets.dart';
import 'package:kernel/ast.dart';
import 'package:kernel/core_types.dart';
import 'package:kernel/kernel.dart';
import 'package:test/test.dart';
import 'package:vm/transformations/deferred_loading.dart'
Expand All @@ -24,7 +25,9 @@ runTestCase(Uri source) async {
final reversed = component.libraries.reversed.toList();
component.libraries.setAll(0, reversed);

component = transformComponent(component);
final coreTypes = CoreTypes(component);

component = transformComponent(component, coreTypes, target);

// Remove core libraries so the expected output isn't enormous and broken by
// core libraries changes.
Expand Down
10 changes: 10 additions & 0 deletions runtime/vm/compiler/frontend/kernel_translation_helper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1930,6 +1930,16 @@ void LoadingUnitsMetadataHelper::ReadMetadata(intptr_t node_offset) {
object_store->set_loading_units(loading_units);
ASSERT(object_store->loading_unit_uris() == Array::null());
object_store->set_loading_unit_uris(loading_unit_uris);

const GrowableObjectArray& libraries =
GrowableObjectArray::Handle(zone, object_store->libraries());
for (intptr_t i = 0; i < libraries.Length(); i++) {
lib ^= libraries.At(i);
unit = lib.loading_unit();
if (unit.IsNull()) {
FATAL("%s is not attributed to any loading unit", lib.ToCString());
}
}
}

CallSiteAttributesMetadataHelper::CallSiteAttributesMetadataHelper(
Expand Down

0 comments on commit 9c2a91f

Please sign in to comment.