mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 16:41:07 +00:00
Add support for SDK outline in KernelDriver.
I had to weaken file system createDirectory() to avoid conflicts when we re-create SDK, and attempt to re-recreate its directory. R=ahe@google.com, paulberry@google.com, sigmund@google.com BUG= Review-Url: https://codereview.chromium.org/2993093003 .
This commit is contained in:
parent
ae4cbb50af
commit
c28419bce0
|
@ -63,15 +63,11 @@ class MemoryFileSystemEntity implements FileSystemEntity {
|
|||
|
||||
/// Create a directory for this file system entry.
|
||||
///
|
||||
/// If the entry already exists, either as a file, or as a directory,
|
||||
/// this is an error.
|
||||
/// If the entry is an existing file, this is an error.
|
||||
void createDirectory() {
|
||||
if (_fileSystem._files[uri] != null) {
|
||||
throw new FileSystemException(uri, 'Entry $uri is a file.');
|
||||
}
|
||||
if (_fileSystem._directories.contains(uri)) {
|
||||
throw new FileSystemException(uri, 'Directory $uri already exists.');
|
||||
}
|
||||
_fileSystem._directories.add(uri);
|
||||
}
|
||||
|
||||
|
|
|
@ -281,6 +281,10 @@ class FileSystemState {
|
|||
/// contain `file:*` URIs as keys.
|
||||
final Map<Uri, FileState> _fileUriToFile = {};
|
||||
|
||||
/// The set of absolute URIs with the `dart` scheme that should be skipped.
|
||||
/// We do this when we use SDK outline instead of compiling SDK sources.
|
||||
final Set<Uri> skipSdkLibraries = new Set<Uri>();
|
||||
|
||||
FileSystemState(this._byteStore, this.fileSystem, this.uriTranslator,
|
||||
this._salt, this._newFileFn);
|
||||
|
||||
|
@ -333,6 +337,11 @@ class FileSystemState {
|
|||
///
|
||||
/// The returned file has the last known state since it was last refreshed.
|
||||
Future<FileState> getFile(Uri absoluteUri) async {
|
||||
// We don't need to process SDK libraries if we have SDK outline.
|
||||
if (skipSdkLibraries.contains(absoluteUri)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Resolve the absolute URI into the absolute file URI.
|
||||
Uri fileUri;
|
||||
if (absoluteUri.isScheme('file')) {
|
||||
|
|
|
@ -51,6 +51,10 @@ class KernelDriver {
|
|||
/// Options used by the kernel compiler.
|
||||
final ProcessedOptions _options;
|
||||
|
||||
/// The optional SDK outline as a serialized program.
|
||||
/// If provided, the driver will not attempt to read SDK files.
|
||||
final List<int> _sdkOutlineBytes;
|
||||
|
||||
/// The logger to report compilation progress.
|
||||
final PerformanceLog _logger;
|
||||
|
||||
|
@ -68,6 +72,10 @@ class KernelDriver {
|
|||
/// reading the file contents.
|
||||
final KernelDriverFileAddedFn _fileAddedFn;
|
||||
|
||||
/// The optional SDK outline loaded from [_sdkOutlineBytes].
|
||||
/// Might be `null` if the bytes are not provided, or if not loaded yet.
|
||||
Program _sdkOutline;
|
||||
|
||||
/// The salt to mix into all hashes used as keys for serialized data.
|
||||
List<int> _salt;
|
||||
|
||||
|
@ -82,10 +90,11 @@ class KernelDriver {
|
|||
final _TestView _testView = new _TestView();
|
||||
|
||||
KernelDriver(this._options, this._uriTranslator,
|
||||
{KernelDriverFileAddedFn fileAddedFn})
|
||||
{List<int> sdkOutlineBytes, KernelDriverFileAddedFn fileAddedFn})
|
||||
: _logger = _options.logger,
|
||||
_fileSystem = _options.fileSystem,
|
||||
_byteStore = _options.byteStore,
|
||||
_sdkOutlineBytes = sdkOutlineBytes,
|
||||
_fileAddedFn = fileAddedFn {
|
||||
_computeSalt();
|
||||
|
||||
|
@ -122,6 +131,10 @@ class KernelDriver {
|
|||
return await runWithFrontEndContext('Compute delta', () async {
|
||||
await _refreshInvalidatedFiles();
|
||||
|
||||
// Load the SDK outline before building the graph, so that the file
|
||||
// system state is configured to skip SDK libraries.
|
||||
await _loadSdkOutline();
|
||||
|
||||
// Ensure that the graph starting at the entry point is ready.
|
||||
FileState entryLibrary =
|
||||
await _logger.runAsync('Build graph of files', () async {
|
||||
|
@ -138,6 +151,12 @@ class KernelDriver {
|
|||
DillTarget dillTarget = new DillTarget(
|
||||
new Ticker(isVerbose: false), _uriTranslator, _options.target);
|
||||
|
||||
// If there is SDK outline, load it.
|
||||
if (_sdkOutline != null) {
|
||||
dillTarget.loader.appendLibraries(_sdkOutline);
|
||||
await dillTarget.buildOutlines();
|
||||
}
|
||||
|
||||
List<LibraryCycleResult> results = [];
|
||||
_testView.compiledCycles.clear();
|
||||
await _logger.runAsync('Compute results for cycles', () async {
|
||||
|
@ -297,6 +316,9 @@ class KernelDriver {
|
|||
var saltBuilder = new ApiSignature();
|
||||
saltBuilder.addInt(DATA_VERSION);
|
||||
saltBuilder.addBool(_options.strongMode);
|
||||
if (_sdkOutlineBytes != null) {
|
||||
saltBuilder.addBytes(_sdkOutlineBytes);
|
||||
}
|
||||
_salt = saltBuilder.toByteList();
|
||||
}
|
||||
|
||||
|
@ -335,6 +357,23 @@ class KernelDriver {
|
|||
return signatureBuilder.toHex();
|
||||
}
|
||||
|
||||
/// Load the SDK outline if its bytes are provided, and configure the file
|
||||
/// system state to skip SDK library files.
|
||||
Future<Null> _loadSdkOutline() async {
|
||||
if (_sdkOutlineBytes != null) {
|
||||
if (_sdkOutline == null) {
|
||||
await _logger.runAsync('Load SDK outline from bytes.', () async {
|
||||
_sdkOutline = new Program();
|
||||
new BinaryBuilder(_sdkOutlineBytes).readProgram(_sdkOutline);
|
||||
// Configure the file system state to skip the outline libraries.
|
||||
for (var outlineLibrary in _sdkOutline.libraries) {
|
||||
_fsState.skipSdkLibraries.add(outlineLibrary.importUri);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Refresh all the invalidated files and update dependencies.
|
||||
Future<Null> _refreshInvalidatedFiles() async {
|
||||
await _logger.runAsync('Refresh invalidated files', () async {
|
||||
|
|
|
@ -44,7 +44,8 @@ class FileTest extends _BaseTestNative {
|
|||
|
||||
test_createDirectory_exists_asDirectory() async {
|
||||
file.createDirectory();
|
||||
expect(() => file.createDirectory(), _throwsFileSystemException);
|
||||
file.createDirectory();
|
||||
expect(await file.exists(), true);
|
||||
}
|
||||
|
||||
test_createDirectory_exists_asFile() async {
|
||||
|
|
|
@ -12,6 +12,7 @@ import 'package:front_end/src/fasta/kernel/utils.dart';
|
|||
import 'package:front_end/src/fasta/uri_translator_impl.dart';
|
||||
import 'package:front_end/src/incremental/byte_store.dart';
|
||||
import 'package:front_end/src/incremental/kernel_driver.dart';
|
||||
import 'package:front_end/summary_generator.dart';
|
||||
import 'package:kernel/ast.dart';
|
||||
import 'package:kernel/binary/ast_from_binary.dart';
|
||||
import 'package:kernel/target/targets.dart';
|
||||
|
@ -286,6 +287,34 @@ static field (core::String) → core::int f;
|
|||
expect(result.types.hierarchy, isNotNull);
|
||||
}
|
||||
|
||||
test_compile_useSdkOutline() async {
|
||||
List<int> sdkOutlineBytes = await _computeSdkOutlineBytes();
|
||||
|
||||
// Configure the driver to use the SDK outline.
|
||||
_createDriver(sdkOutlineBytes: sdkOutlineBytes);
|
||||
|
||||
writeFile('/test/.packages', 'test:lib/');
|
||||
String aPath = '/test/lib/a.dart';
|
||||
Uri aUri = writeFile(aPath, r'''
|
||||
import 'dart:async';
|
||||
var a = 1;
|
||||
Future<String> b;
|
||||
''');
|
||||
|
||||
KernelResult result = await driver.getKernel(aUri);
|
||||
|
||||
// The result does not include SDK libraries.
|
||||
_assertLibraryUris(result,
|
||||
includes: [aUri],
|
||||
excludes: [Uri.parse('dart:core'), Uri.parse('dart:core')]);
|
||||
|
||||
// The types of top-level variables are resolved.
|
||||
var library = _getLibrary(result, aUri);
|
||||
expect(library.fields[0].type.toString(), 'dart.core::int');
|
||||
expect(library.fields[1].type.toString(),
|
||||
'dart.async::Future<dart.core::String>');
|
||||
}
|
||||
|
||||
test_limitedStore_exportDependencies() async {
|
||||
writeFile('/test/.packages', 'test:lib/');
|
||||
String aPath = '/test/lib/a.dart';
|
||||
|
@ -647,20 +676,35 @@ import 'b.dart';
|
|||
}
|
||||
}
|
||||
|
||||
Future<List<int>> _computeSdkOutlineBytes() async {
|
||||
var options = new CompilerOptions()
|
||||
..fileSystem = fileSystem
|
||||
..sdkRoot = Uri.parse('file:///sdk/')
|
||||
..compileSdk = true
|
||||
..chaseDependencies = true
|
||||
..strongMode = true
|
||||
..target = new NoneTarget(new TargetFlags(strongMode: true));
|
||||
var inputs = [Uri.parse('dart:core')];
|
||||
return summaryFor(inputs, options);
|
||||
}
|
||||
|
||||
/// Create new [KernelDriver] instance and put it into the [driver] field.
|
||||
void _createDriver(
|
||||
{Map<String, Uri> packages, KernelDriverFileAddedFn fileAddedFn}) {
|
||||
{List<int> sdkOutlineBytes,
|
||||
Map<String, Uri> packages,
|
||||
KernelDriverFileAddedFn fileAddedFn}) {
|
||||
var uriTranslator = new UriTranslatorImpl(
|
||||
createSdkFiles(fileSystem), new MapPackages(packages));
|
||||
driver = new KernelDriver(
|
||||
new ProcessedOptions(new CompilerOptions()
|
||||
..logger = new PerformanceLog(null)
|
||||
..fileSystem = fileSystem
|
||||
..byteStore = new MemoryByteStore()
|
||||
..strongMode = true
|
||||
..target = new NoneTarget(new TargetFlags(strongMode: true))),
|
||||
uriTranslator,
|
||||
fileAddedFn: fileAddedFn);
|
||||
|
||||
var options = new CompilerOptions()
|
||||
..logger = new PerformanceLog(null)
|
||||
..fileSystem = fileSystem
|
||||
..byteStore = new MemoryByteStore()
|
||||
..strongMode = true
|
||||
..target = new NoneTarget(new TargetFlags(strongMode: true));
|
||||
|
||||
driver = new KernelDriver(new ProcessedOptions(options), uriTranslator,
|
||||
sdkOutlineBytes: sdkOutlineBytes, fileAddedFn: fileAddedFn);
|
||||
}
|
||||
|
||||
Library _getLibrary(KernelResult result, Uri uri) {
|
||||
|
|
|
@ -5,22 +5,45 @@
|
|||
import 'package:front_end/memory_file_system.dart';
|
||||
import 'package:front_end/src/base/libraries_specification.dart';
|
||||
|
||||
/// Create SDK libraries which are used by Fasta to perform kernel generation.
|
||||
/// The root of the SDK is `file:///sdk`, it will contain a libraries
|
||||
/// specification file at `lib/libraries.json`.
|
||||
///
|
||||
/// Returns the [TargetLibrariesSpecification] whose contents are in
|
||||
/// libraries.json.
|
||||
TargetLibrariesSpecification createSdkFiles(MemoryFileSystem fileSystem) {
|
||||
Map<String, LibraryInfo> dartLibraries = {};
|
||||
void addSdkLibrary(String name, String contents) {
|
||||
String path = '$name/$name.dart';
|
||||
Uri uri = Uri.parse('file:///sdk/lib/$path');
|
||||
fileSystem.entityForUri(uri).writeAsStringSync(contents);
|
||||
dartLibraries[name] = new LibraryInfo(name, uri, const []);
|
||||
}
|
||||
final _ASYNC = r'''
|
||||
library dart.async;
|
||||
|
||||
addSdkLibrary('core', r'''
|
||||
class Future<T> {
|
||||
factory Future(computation()) => null;
|
||||
factory Future.delayed(Duration duration, [T computation()]) => null;
|
||||
factory Future.microtask(FutureOr<T> computation()) => null;
|
||||
factory Future.value([value]) => null;
|
||||
|
||||
static Future<List<T>> wait<T>(Iterable<Future<T>> futures) => null;
|
||||
Future<R> then<R>(FutureOr<R> onValue(T value)) => null;
|
||||
|
||||
Future<T> whenComplete(action());
|
||||
}
|
||||
|
||||
|
||||
class FutureOr<T> {}
|
||||
class Stream<T> {}
|
||||
abstract class StreamIterator<T> {}
|
||||
|
||||
abstract class Completer<T> {
|
||||
factory Completer() => null;
|
||||
factory Completer.sync() => null;
|
||||
Future<T> get future;
|
||||
void complete([FutureOr<T> value]);
|
||||
void completeError(Object error, [StackTrace stackTrace]);
|
||||
bool get isCompleted;
|
||||
}
|
||||
|
||||
class _StreamIterator<T> implements StreamIterator<T> {}
|
||||
class _AsyncStarStreamController {}
|
||||
Object _asyncStackTraceHelper(Function async_op) { }
|
||||
Function _asyncThenWrapperHelper(continuation) {}
|
||||
Function _asyncErrorWrapperHelper(continuation) {}
|
||||
Future _awaitHelper(
|
||||
object, Function thenCallback, Function errorCallback, var awaiter) {}
|
||||
''';
|
||||
|
||||
final _CORE = r'''
|
||||
library dart.core;
|
||||
import 'dart:_internal';
|
||||
import 'dart:async';
|
||||
|
@ -203,45 +226,27 @@ external bool identical(Object a, Object b);
|
|||
void print(Object o) {}
|
||||
|
||||
abstract class _SyncIterable implements Iterable {}
|
||||
''');
|
||||
''';
|
||||
|
||||
addSdkLibrary('async', r'''
|
||||
library dart.async;
|
||||
/// Create SDK libraries which are used by Fasta to perform kernel generation.
|
||||
/// The root of the SDK is `file:///sdk`, it will contain a libraries
|
||||
/// specification file at `lib/libraries.json`.
|
||||
///
|
||||
/// Returns the [TargetLibrariesSpecification] whose contents are in
|
||||
/// libraries.json.
|
||||
TargetLibrariesSpecification createSdkFiles(MemoryFileSystem fileSystem) {
|
||||
Map<String, LibraryInfo> dartLibraries = {};
|
||||
void addSdkLibrary(String name, String contents) {
|
||||
String path = '$name/$name.dart';
|
||||
Uri uri = Uri.parse('file:///sdk/lib/$path');
|
||||
fileSystem.entityForUri(uri).writeAsStringSync(contents);
|
||||
dartLibraries[name] = new LibraryInfo(name, uri, const []);
|
||||
}
|
||||
|
||||
class Future<T> {
|
||||
factory Future(computation()) => null;
|
||||
factory Future.delayed(Duration duration, [T computation()]) => null;
|
||||
factory Future.microtask(FutureOr<T> computation()) => null;
|
||||
factory Future.value([value]) => null;
|
||||
fileSystem.entityForUri(Uri.parse('file:///sdk/')).createDirectory();
|
||||
|
||||
static Future<List<T>> wait<T>(Iterable<Future<T>> futures) => null;
|
||||
Future<R> then<R>(FutureOr<R> onValue(T value)) => null;
|
||||
|
||||
Future<T> whenComplete(action());
|
||||
}
|
||||
|
||||
|
||||
class FutureOr<T> {}
|
||||
class Stream<T> {}
|
||||
abstract class StreamIterator<T> {}
|
||||
|
||||
abstract class Completer<T> {
|
||||
factory Completer() => null;
|
||||
factory Completer.sync() => null;
|
||||
Future<T> get future;
|
||||
void complete([FutureOr<T> value]);
|
||||
void completeError(Object error, [StackTrace stackTrace]);
|
||||
bool get isCompleted;
|
||||
}
|
||||
|
||||
class _StreamIterator<T> implements StreamIterator<T> {}
|
||||
class _AsyncStarStreamController {}
|
||||
Object _asyncStackTraceHelper(Function async_op) { }
|
||||
Function _asyncThenWrapperHelper(continuation) {}
|
||||
Function _asyncErrorWrapperHelper(continuation) {}
|
||||
Future _awaitHelper(
|
||||
object, Function thenCallback, Function errorCallback, var awaiter) {}
|
||||
''');
|
||||
addSdkLibrary('core', _CORE);
|
||||
addSdkLibrary('async', _ASYNC);
|
||||
|
||||
addSdkLibrary('collection', 'library dart.collection;');
|
||||
addSdkLibrary('convert', 'library dart.convert;');
|
||||
|
@ -256,7 +261,6 @@ external double sin(num radians);
|
|||
addSdkLibrary('nativewrappers', 'library dart.nativewrappers;');
|
||||
addSdkLibrary('profiler', 'library dart.profiler;');
|
||||
addSdkLibrary('typed_data', 'library dart.typed_data;');
|
||||
addSdkLibrary('vmservice_io', 'library dart.vmservice_io;');
|
||||
addSdkLibrary('_builtin', 'library dart._builtin;');
|
||||
addSdkLibrary('_internal', '''
|
||||
library dart._internal;
|
||||
|
@ -266,10 +270,9 @@ class ExternalName {
|
|||
const ExternalName(this.name);
|
||||
}
|
||||
''');
|
||||
addSdkLibrary('_vmservice', 'library dart._vmservice;');
|
||||
|
||||
var targetSpec = new TargetLibrariesSpecification('vm', dartLibraries);
|
||||
var spec = new LibrariesSpecification({'vm': targetSpec});
|
||||
var targetSpec = new TargetLibrariesSpecification(null, dartLibraries);
|
||||
var spec = new LibrariesSpecification({'none': targetSpec, 'vm': targetSpec});
|
||||
|
||||
Uri uri = Uri.parse('file:///sdk/lib/libraries.json');
|
||||
fileSystem.entityForUri(uri).writeAsStringSync(spec.toJsonString(uri));
|
||||
|
|
Loading…
Reference in a new issue