@@ -25,6 +25,9 @@ import 'package:kernel/kernel.dart'
2525import 'package:path/path.dart' as path;
2626import 'package:usage/uuid/uuid.dart' ;
2727
28+ import 'package:vm/bytecode/gen_bytecode.dart'
29+ show generateBytecode, createFreshComponentWithBytecode;
30+ import 'package:vm/bytecode/options.dart' show BytecodeOptions;
2831import 'package:vm/incremental_compiler.dart' show IncrementalCompiler;
2932import 'package:vm/kernel_front_end.dart'
3033 show
@@ -34,6 +37,7 @@ import 'package:vm/kernel_front_end.dart'
3437 convertFileOrUriArgumentToUri,
3538 createFrontEndTarget,
3639 createFrontEndFileSystem,
40+ runWithFrontEndCompilerContext,
3741 setVMEnvironmentDefines,
3842 writeDepfile;
3943
@@ -116,6 +120,16 @@ ArgParser argParser = new ArgParser(allowTrailingOptions: true)
116120 ..addFlag ('track-widget-creation' ,
117121 help: 'Run a kernel transformer to track creation locations for widgets.' ,
118122 defaultsTo: false )
123+ ..addFlag ('gen-bytecode' , help: 'Generate bytecode' , defaultsTo: false )
124+ ..addMultiOption ('bytecode-options' ,
125+ help: 'Specify options for bytecode generation:' ,
126+ valueHelp: 'opt1,opt2,...' ,
127+ allowed: BytecodeOptions .commandLineFlags.keys,
128+ allowedHelp: BytecodeOptions .commandLineFlags)
129+ ..addFlag ('drop-ast' ,
130+ help: 'Include only bytecode into the output file' , defaultsTo: false )
131+ ..addFlag ('enable-asserts' ,
132+ help: 'Whether asserts will be enabled.' , defaultsTo: false )
119133 ..addMultiOption ('enable-experiment' ,
120134 help: 'Comma separated list of experimental features, eg set-literals.' ,
121135 hide: true );
@@ -238,6 +252,7 @@ class FrontendCompiler implements CompilerInterface {
238252 bool unsafePackageSerialization;
239253
240254 CompilerOptions _compilerOptions;
255+ BytecodeOptions _bytecodeOptions;
241256 FileSystem _fileSystem;
242257 Uri _mainSource;
243258 ArgResults _options;
@@ -323,6 +338,12 @@ class FrontendCompiler implements CompilerInterface {
323338 return false ;
324339 }
325340
341+ compilerOptions.bytecode = options['gen-bytecode' ];
342+ final BytecodeOptions bytecodeOptions = new BytecodeOptions (
343+ enableAsserts: options['enable-asserts' ],
344+ environmentDefines: environmentDefines)
345+ ..parseCommandLineFlags (options['bytecode-options' ]);
346+
326347 compilerOptions.target = createFrontEndTarget (
327348 options['target' ],
328349 trackWidgetCreation: options['track-widget-creation' ],
@@ -342,13 +363,15 @@ class FrontendCompiler implements CompilerInterface {
342363 Component component;
343364 if (options['incremental' ]) {
344365 _compilerOptions = compilerOptions;
366+ _bytecodeOptions = bytecodeOptions;
345367 setVMEnvironmentDefines (environmentDefines, _compilerOptions);
346368
347369 _compilerOptions.omitPlatform = false ;
348370 _generator =
349371 generator ?? _createGenerator (new Uri .file (_initializeFromDill));
350372 await invalidateIfInitializingFromDill ();
351- component = await _runWithPrintRedirection (() => _generator.compile ());
373+ component = await _runWithPrintRedirection (() async =>
374+ await _generateBytecodeIfNeeded (await _generator.compile ()));
352375 } else {
353376 if (options['link-platform' ]) {
354377 // TODO(aam): Remove linkedDependencies once platform is directly embedded
@@ -362,6 +385,9 @@ class FrontendCompiler implements CompilerInterface {
362385 aot: options['aot' ],
363386 useGlobalTypeFlowAnalysis: options['tfa' ],
364387 environmentDefines: environmentDefines,
388+ genBytecode: compilerOptions.bytecode,
389+ bytecodeOptions: bytecodeOptions,
390+ dropAST: options['drop-ast' ],
365391 useProtobufTreeShaker: options['protobuf-tree-shaker' ]));
366392 }
367393 if (component != null ) {
@@ -388,6 +414,22 @@ class FrontendCompiler implements CompilerInterface {
388414 return errors.isEmpty;
389415 }
390416
417+ Future <Component > _generateBytecodeIfNeeded (Component component) async {
418+ if (_compilerOptions.bytecode && errors.isEmpty) {
419+ await runWithFrontEndCompilerContext (
420+ _mainSource, _compilerOptions, component, () {
421+ generateBytecode (component,
422+ coreTypes: _generator.getCoreTypes (),
423+ hierarchy: _generator.getClassHierarchy (),
424+ options: _bytecodeOptions);
425+ if (_options['drop-ast' ]) {
426+ component = createFreshComponentWithBytecode (component);
427+ }
428+ });
429+ }
430+ return component;
431+ }
432+
391433 void _outputDependenciesDelta (Component component) async {
392434 Set <Uri > uris = new Set <Uri >();
393435 for (Uri uri in component.uriToSource.keys) {
@@ -501,12 +543,12 @@ class FrontendCompiler implements CompilerInterface {
501543 _mainSource = _getFileOrUri (entryPoint);
502544 }
503545 errors.clear ();
504- final Component deltaProgram =
505- await _generator.compile (entryPoint: _mainSource);
546+ Component deltaProgram = await _generator.compile (entryPoint: _mainSource);
506547
507548 if (deltaProgram != null && transformer != null ) {
508549 transformer.transform (deltaProgram);
509550 }
551+ deltaProgram = await _generateBytecodeIfNeeded (deltaProgram);
510552 await writeDillFile (deltaProgram, _kernelBinaryFilename);
511553 _outputStream.writeln (boundaryKey);
512554 await _outputDependenciesDelta (deltaProgram);
@@ -528,8 +570,10 @@ class FrontendCompiler implements CompilerInterface {
528570 Procedure procedure = await _generator.compileExpression (
529571 expression, definitions, typeDefinitions, libraryUri, klass, isStatic);
530572 if (procedure != null ) {
573+ Component component = createExpressionEvaluationComponent (procedure);
574+ component = await _generateBytecodeIfNeeded (component);
531575 final IOSink sink = new File (_kernelBinaryFilename).openWrite ();
532- sink.add (serializeProcedure (procedure ));
576+ sink.add (serializeComponent (component ));
533577 await sink.close ();
534578 _outputStream
535579 .writeln ('$boundaryKey $_kernelBinaryFilename ${errors .length }' );
0 commit comments