Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(199)

Side by Side Diff: runtime/tools/kernel-service.dart

Issue 2665753002: Reapply "Create an app snapshot of the Dart front end." (Closed)
Patch Set: . Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4 library runtime.tools.kernel_service;
5
6 // This is an interface to the Dart Kernel parser and Kernel binary generator.
7 //
8 // It is used by the kernel-isolate to load Dart source code and generate
9 // Kernel binary format.
10 //
11
12 import 'dart:async';
13 import 'dart:convert';
14 import 'dart:io';
15 import 'dart:isolate';
16 import 'dart:typed_data';
17
18 import 'package:kernel/analyzer/loader.dart';
19 import 'package:kernel/binary/ast_to_binary.dart';
20 import 'package:kernel/kernel.dart';
21 import 'package:kernel/target/targets.dart';
22
23 const bool verbose = const bool.fromEnvironment('DFE_VERBOSE') ?? false;
24
25 class DataSink implements Sink<List<int>> {
26 final BytesBuilder builder = new BytesBuilder();
27
28 void add(List<int> data) {
29 builder.add(data);
30 }
31
32 void close() {
33 // Nothing to do.
34 }
35 }
36
37 // Note: these values must match Dart_KernelCompilationStatus in dart_api.h.
38 const int STATUS_OK = 0; // Compilation was successful.
39 const int STATUS_ERROR = 1; // Compilation failed with a compile time error.
40 const int STATUS_CRASH = 2; // Compiler crashed.
41
42 abstract class CompilationResult {
43 List toResponse();
44 }
45
46 class CompilationOk extends CompilationResult {
47 final Uint8List binary;
48
49 CompilationOk(this.binary);
50
51 List toResponse() => [STATUS_OK, binary];
52
53 String toString() => "CompilationOk(${binary.length} bytes)";
54 }
55
56 abstract class CompilationFail extends CompilationResult {
57 String get errorString;
58 }
59
60 class CompilationError extends CompilationFail {
61 final List<String> errors;
62
63 CompilationError(this.errors);
64
65 List toResponse() => [STATUS_ERROR, errorString];
66
67 String get errorString => errors.take(10).join('\n');
68
69 String toString() => "CompilationError(${errorString})";
70 }
71
72 class CompilationCrash extends CompilationFail {
73 final String exception;
74 final String stack;
75
76 CompilationCrash(this.exception, this.stack);
77
78 List toResponse() => [STATUS_CRASH, errorString];
79
80 String get errorString => "${exception}\n${stack}";
81
82 String toString() => "CompilationCrash(${errorString})";
83 }
84
85 Future<CompilationResult> parseScriptImpl(DartLoaderBatch batch_loader,
86 Uri fileName, String packageConfig, String sdkPath) async {
87 if (!FileSystemEntity.isFileSync(fileName.path)) {
88 throw "Input file '${fileName.path}' does not exist.";
89 }
90
91 if (!FileSystemEntity.isDirectorySync(sdkPath)) {
92 throw "Patched sdk directory not found at $sdkPath";
93 }
94
95 Target target = getTarget("vm", new TargetFlags(strongMode: false));
96 DartOptions dartOptions = new DartOptions(
97 strongMode: false,
98 strongModeSdk: false,
99 sdk: sdkPath,
100 packagePath: packageConfig,
101 customUriMappings: const {},
102 declaredVariables: const {});
103 DartLoader loader =
104 await batch_loader.getLoader(new Repository(), dartOptions);
105 var program = loader.loadProgram(fileName, target: target);
106
107 var errors = loader.errors;
108 if (errors.isNotEmpty) {
109 return new CompilationError(loader.errors.toList());
110 }
111
112 // Link program into one file, cf. --link option in dartk.
113 target.transformProgram(program);
114
115 // Write the program to a list of bytes and return it.
116 var sink = new DataSink();
117 new BinaryPrinter(sink).writeProgramFile(program);
118 return new CompilationOk(sink.builder.takeBytes());
119 }
120
121 Future<CompilationResult> parseScript(DartLoaderBatch loader, Uri fileName,
122 String packageConfig, String sdkPath) async {
123 try {
124 return await parseScriptImpl(loader, fileName, packageConfig, sdkPath);
125 } catch (err, stack) {
126 return new CompilationCrash(err.toString(), stack.toString());
127 }
128 }
129
130 Future _processLoadRequestImpl(String inputFileUrl) async {
131 Uri scriptUri = Uri.parse(inputFileUrl);
132
133 // Because we serve both Loader and bootstrapping requests we need to
134 // duplicate the logic from _resolveScriptUri(...) here and attempt to
135 // resolve schemaless uris using current working directory.
136 if (scriptUri.scheme == '') {
137 // Script does not have a scheme, assume that it is a path,
138 // resolve it against the working directory.
139 scriptUri = Directory.current.uri.resolveUri(scriptUri);
140 }
141
142 if (scriptUri.scheme != 'file') {
143 // TODO: reuse loader code to support other schemes.
144 throw "Expected 'file' scheme for a script uri: got ${scriptUri.scheme}";
145 }
146
147 final Uri packagesUri = (Platform.packageConfig != null)
148 ? Uri.parse(Platform.packageConfig)
149 : await _findPackagesFile(scriptUri);
150 if (packagesUri == null) {
151 throw "Could not find .packages";
152 }
153
154 final Uri patchedSdk =
155 Uri.parse(Platform.resolvedExecutable).resolve("patched_sdk");
156
157 if (verbose) {
158 print("""DFE: Requesting compilation {
159 scriptUri: ${scriptUri}
160 packagesUri: ${packagesUri}
161 patchedSdk: ${patchedSdk}
162 }""");
163 }
164
165 return await parseScript(
166 new DartLoaderBatch(), scriptUri, packagesUri.path, patchedSdk.path);
167 }
168
169 // Process a request from the runtime. See KernelIsolate::CompileToKernel in
170 // kernel_isolate.cc and Loader::SendKernelRequest in loader.cc.
171 Future _processLoadRequest(request) async {
172 if (verbose) {
173 print("DFE: request: $request");
174 print("DFE: Platform.packageConfig: ${Platform.packageConfig}");
175 print("DFE: Platform.resolvedExecutable: ${Platform.resolvedExecutable}");
176 }
177
178 final int tag = request[0];
179 final SendPort port = request[1];
180 final String inputFileUrl = request[2];
181
182 var result;
183 try {
184 result = await _processLoadRequestImpl(inputFileUrl);
185 } catch (error, stack) {
186 result = new CompilationCrash(error.toString(), stack.toString());
187 }
188
189 if (verbose) {
190 print("DFE:> ${result}");
191 }
192
193 // Check whether this is a Loader request or a bootstrapping request from
194 // KernelIsolate::CompileToKernel.
195 final isBootstrapRequest = tag == null;
196 if (isBootstrapRequest) {
197 port.send(result.toResponse());
198 } else {
199 // See loader.cc for the code that handles these replies.
200 if (result is CompilationOk) {
201 port.send([tag, inputFileUrl, inputFileUrl, null, result]);
202 } else {
203 port.send([-tag, inputFileUrl, inputFileUrl, null, result.errorString]);
204 }
205 }
206 }
207
208 main() => new RawReceivePort()..handler = _processLoadRequest;
209
210 // This duplicates functionality from the Loader which we can't easily
211 // access from here.
212 Uri _findPackagesFile(Uri base) async {
213 var dir = new File.fromUri(base).parent;
214 while (true) {
215 final packagesFile = dir.uri.resolve(".packages");
216 if (await new File.fromUri(packagesFile).exists()) {
217 return packagesFile;
218 }
219 if (dir.parent == dir) {
220 break;
221 }
222 dir = dir.parent;
223 }
224 return null;
225 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698