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

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

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

Powered by Google App Engine
This is Rietveld 408576698