3dce89fbe0
Not having to do the read-allocate-copy dance for files to add a 0-byte at the end results in these changes when using the CFE to compile (a fixed version of) the CFE: ``` msec task-clock:u: -1.7356% +/- 0.2164% (-73.16 +/- 9.12) page-faults:u: -2.6957% +/- 0.0111% (-2914.83 +/- 12.00) cycles:u: -1.7128% +/- 0.2223% (-297927979.70 +/- 38660477.01) instructions:u: -1.6814% +/- 0.0002% (-361315766.86 +/- 36853.71) branch-misses:u: -3.3289% +/- 0.9669% (-2153126.00 +/- 625370.97) seconds time elapsed: -1.7372% +/- 0.2154% (-0.07 +/- 0.01) seconds user: -1.5998% +/- 0.2740% (-0.06 +/- 0.01) seconds sys: -4.1451% +/- 2.9801% (-0.01 +/- 0.01) Scavenge( new space) goes from 62 to 61 ``` TEST=Existing test coverage. Change-Id: I8e182bcee39839f6ed1e658c30c85c40ecf0b259 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/385722 Reviewed-by: Johnni Winther <johnniwinther@google.com> Reviewed-by: Morgan :) <davidmorgan@google.com> Reviewed-by: Daco Harkes <dacoharkes@google.com> Reviewed-by: Srujan Gaddam <srujzs@google.com> Commit-Queue: Jens Johansen <jensj@google.com> Reviewed-by: Mayank Patke <fishythefish@google.com> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
263 lines
8.8 KiB
Dart
263 lines
8.8 KiB
Dart
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
library compiler;
|
|
|
|
import 'dart:async';
|
|
import 'dart:typed_data';
|
|
|
|
import 'package:front_end/src/api_unstable/dart2js.dart' as fe;
|
|
|
|
import 'src/compiler.dart';
|
|
import 'src/diagnostics/messages.dart';
|
|
import 'src/options.dart';
|
|
|
|
/// Kind of diagnostics that the compiler can report.
|
|
enum Diagnostic {
|
|
/// An error as identified by the "Dart Programming Language
|
|
/// Specification" [https://dart.dev/guides/language/spec].
|
|
///
|
|
/// Note: the compiler may still produce an executable result after
|
|
/// reporting a compilation error. The specification says:
|
|
///
|
|
/// "A compile-time error must be reported by a Dart compiler before
|
|
/// the erroneous code is executed." and "If a compile-time error
|
|
/// occurs within the code of a running isolate A, A is immediately
|
|
/// suspended."
|
|
///
|
|
/// This means that the compiler can generate code that when executed
|
|
/// terminates execution.
|
|
error('error'),
|
|
|
|
/// A warning as identified by the "Dart Programming Language
|
|
/// Specification" [https://dart.dev/guides/language/spec].
|
|
warning('warning'),
|
|
|
|
/// Any other warning that is not covered by [warning].
|
|
hint('hint'),
|
|
|
|
/// Informational message about the compiler.
|
|
info('info'),
|
|
|
|
/// Informational messages that shouldn't be printed unless
|
|
/// explicitly requested by the user of a compiler.
|
|
verboseInfo('verbose info'),
|
|
|
|
/// An internal error in the compiler.
|
|
crash('crash'),
|
|
|
|
/// Additional information about the preceding non-info diagnostic from the
|
|
/// compiler.
|
|
///
|
|
/// For example, consider a duplicated definition. The compiler first emits a
|
|
/// message about the duplicated definition, then emits an info message about
|
|
/// the location of the existing definition.
|
|
context('context'),
|
|
;
|
|
|
|
/// An [int] representation of this kind. The ordinals are designed
|
|
/// to be used as bitsets.
|
|
int get ordinal => 2 << this.index;
|
|
|
|
/// The name of this kind.
|
|
final String name;
|
|
|
|
const Diagnostic(this.name);
|
|
|
|
@override
|
|
String toString() => name;
|
|
}
|
|
|
|
// Unless explicitly allowed, passing `null` for any argument to the
|
|
// methods of library will result in an Error being thrown.
|
|
|
|
/// Input kinds used by [CompilerInput.readFromUri].
|
|
enum InputKind {
|
|
/// Data is read as UTF8 either as a [String] or a zero-terminated
|
|
/// `List<int>`.
|
|
UTF8,
|
|
|
|
/// Data is read as bytes in a `List<int>`.
|
|
binary,
|
|
}
|
|
|
|
/// Interface for data read through [CompilerInput.readFromUri].
|
|
abstract class Input<T> {
|
|
/// The URI from which data was read.
|
|
Uri get uri;
|
|
|
|
/// The format of the read [data].
|
|
InputKind get inputKind;
|
|
|
|
/// The raw data read from [uri].
|
|
T get data;
|
|
|
|
/// Release any resources held by the input. After releasing, a call to `get
|
|
/// data` will fail, and previously returned data may be invalid.
|
|
void release();
|
|
}
|
|
|
|
/// Interface for providing the compiler with input. That is, Dart source files,
|
|
/// package config files, etc.
|
|
abstract class CompilerInput {
|
|
/// Returns a future that completes to the source corresponding to [uri].
|
|
/// If an exception occurs, the future completes with this exception.
|
|
///
|
|
/// If [inputKind] is `InputKind.UTF8` the source is represented as a
|
|
/// zero-terminated list of encoded bytes. If the input kind is
|
|
/// `InputKind.binary` the resulting list is the raw bytes from the input
|
|
/// source.
|
|
Future<Input<Uint8List>> readFromUri(Uri uri,
|
|
{InputKind inputKind = InputKind.UTF8});
|
|
|
|
/// Register that [uri] should be an `InputKind.UTF8` input with the
|
|
/// given [source] of contents.
|
|
///
|
|
/// If [uri] was read prior to this call, this registration has no effect,
|
|
/// otherwise it is expected that a future [readFromUri] will return the
|
|
/// contents provided here.
|
|
///
|
|
/// The main purpose of this API is to assist in error reporting when
|
|
/// compiling from kernel binary files. Binary files embed the contents
|
|
/// of source files that may not be available on disk. By using these
|
|
/// registered contents, dart2js will be able to provide accurate line/column
|
|
/// information on an error.
|
|
void registerUtf8ContentsForDiagnostics(Uri uri, Uint8List source);
|
|
}
|
|
|
|
/// Output types used in `CompilerOutput.createOutputSink`.
|
|
enum OutputType {
|
|
/// The main JavaScript output.
|
|
js,
|
|
|
|
/// A deferred JavaScript output part.
|
|
jsPart,
|
|
|
|
/// A source map for a JavaScript output.
|
|
sourceMap,
|
|
|
|
/// Dump info output.
|
|
dumpInfo,
|
|
|
|
/// Deferred map output.
|
|
deferredMap,
|
|
|
|
/// Deferred load ids map output.
|
|
deferredLoadIds,
|
|
|
|
/// Unused libraries output.
|
|
dumpUnusedLibraries,
|
|
|
|
/// Resource identifiers output.
|
|
resourceIdentifiers,
|
|
|
|
/// Implementation specific output used for debugging the compiler.
|
|
debug,
|
|
}
|
|
|
|
/// Sink interface used for generating output from the compiler.
|
|
abstract class OutputSink implements Sink<String> {
|
|
/// Adds [text] to the sink.
|
|
@override
|
|
void add(String text);
|
|
|
|
/// Closes the sink.
|
|
@override
|
|
void close();
|
|
}
|
|
|
|
/// Sink interface used for generating binary data from the compiler.
|
|
abstract class BinaryOutputSink implements Sink<List<int>> {
|
|
/// Writes indices [start] to [end] of [buffer] to the sink.
|
|
@override
|
|
void add(List<int> buffer, [int start = 0, int? end]);
|
|
|
|
/// Closes the sink.
|
|
@override
|
|
void close();
|
|
}
|
|
|
|
/// Interface for producing output from the compiler. That is, JavaScript target
|
|
/// files, source map files, dump info files, etc.
|
|
abstract class CompilerOutput {
|
|
/// Returns an [OutputSink] that will serve as compiler output for the given
|
|
/// component.
|
|
///
|
|
/// Components are identified by [name], [extension], and [type]. By
|
|
/// convention, the empty string `""` will represent the main output of the
|
|
/// provided [type]. [name] and [extension] are otherwise suggestive.
|
|
// TODO(johnniwinther): Replace [name] and [extension] with something like
|
|
// [id] and [uri].
|
|
OutputSink createOutputSink(String name, String extension, OutputType type);
|
|
|
|
/// Returns an [BinaryOutputSink] that will serve as compiler output for the
|
|
/// given URI.
|
|
BinaryOutputSink createBinarySink(Uri uri);
|
|
}
|
|
|
|
/// Interface for receiving diagnostic message from the compiler. That is,
|
|
/// errors, warnings, hints, etc.
|
|
abstract class CompilerDiagnostics {
|
|
/// Invoked by the compiler to report diagnostics. If [uri] is `null`, so are
|
|
/// [begin] and [end]. No other arguments may be `null`. If [uri] is not
|
|
/// `null`, neither are [begin] and [end]. [uri] indicates the compilation
|
|
/// unit from where the diagnostic originates. [begin] and [end] are
|
|
/// zero-based character offsets from the beginning of the compilation unit.
|
|
/// [message] is the diagnostic message, and [kind] indicates what
|
|
/// kind of diagnostic it is.
|
|
///
|
|
/// Experimental: [code] gives access to an id for the messages. Currently it
|
|
/// is the [Message] used to create the diagnostic, if available, from which
|
|
/// the [MessageKind] is accessible.
|
|
void report(Message? code, Uri? uri, int? begin, int? end, String text,
|
|
Diagnostic kind);
|
|
}
|
|
|
|
/// Information resulting from the compilation.
|
|
class CompilationResult {
|
|
/// `true` if the compilation succeeded, that is, compilation didn't fail due
|
|
/// to compile-time errors and/or internal errors.
|
|
final bool isSuccess;
|
|
|
|
/// The compiler object used for the compilation.
|
|
///
|
|
/// Note: The type of [compiler] is implementation dependent and may vary.
|
|
/// Use only for debugging and testing.
|
|
final Compiler? compiler;
|
|
|
|
/// Shared state between compilations.
|
|
///
|
|
/// This is used to speed up batch mode.
|
|
final fe.InitializedCompilerState? kernelInitializedCompilerState;
|
|
|
|
CompilationResult(this.compiler,
|
|
{this.isSuccess = true, this.kernelInitializedCompilerState});
|
|
}
|
|
|
|
// Unless explicitly allowed, passing [:null:] for any argument to the
|
|
// methods of library will result in an Error being thrown.
|
|
|
|
/// Returns a future that completes to a [CompilationResult] when the Dart
|
|
/// sources in [options] have been compiled.
|
|
///
|
|
/// The generated compiler output is obtained by providing a [compilerOutput].
|
|
///
|
|
/// If the compilation fails, the future's `CompilationResult.isSuccess` is
|
|
/// `false` and [CompilerDiagnostics.report] on [compilerDiagnostics]
|
|
/// is invoked at least once with `kind == Diagnostic.ERROR` or
|
|
/// `kind == Diagnostic.CRASH`.
|
|
Future<CompilationResult> compile(
|
|
CompilerOptions compilerOptions,
|
|
CompilerInput compilerInput,
|
|
CompilerDiagnostics compilerDiagnostics,
|
|
CompilerOutput compilerOutput) {
|
|
var compiler = Compiler(
|
|
compilerInput, compilerOutput, compilerDiagnostics, compilerOptions);
|
|
return compiler.run().then((bool success) {
|
|
return CompilationResult(compiler,
|
|
isSuccess: success,
|
|
kernelInitializedCompilerState: compiler.initializedCompilerState);
|
|
});
|
|
}
|