Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 7580e77

Browse files
johnniwinthercommit-bot@chromium.org
authored andcommitted
Support modular code generation
Change-Id: Id5511296eb0b6acf812bc464d71efa4019f211d7 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/103523 Reviewed-by: Sigmund Cherem <[email protected]>
1 parent 225a301 commit 7580e77

File tree

21 files changed

+1119
-197
lines changed

21 files changed

+1119
-197
lines changed

pkg/compiler/lib/src/backend_strategy.dart

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
library dart2js.backend_strategy;
66

77
import 'common.dart';
8+
import 'common/codegen.dart';
89
import 'common/tasks.dart';
910
import 'deferred_load.dart' show OutputUnitData;
1011
import 'enqueue.dart';
@@ -14,6 +15,7 @@ import 'io/source_information.dart';
1415
import 'js_backend/inferred_data.dart';
1516
import 'js_backend/interceptor_data.dart';
1617
import 'js_backend/native_data.dart';
18+
import 'serialization/serialization.dart';
1719
import 'ssa/ssa.dart';
1820
import 'universe/codegen_world_builder.dart';
1921
import 'universe/world_builder.dart';
@@ -40,7 +42,8 @@ abstract class BackendStrategy {
4042
OneShotInterceptorData oneShotInterceptorData);
4143

4244
/// Creates the [WorkItemBuilder] used by the codegen enqueuer.
43-
WorkItemBuilder createCodegenWorkItemBuilder(JClosedWorld closedWorld);
45+
WorkItemBuilder createCodegenWorkItemBuilder(
46+
JClosedWorld closedWorld, CodegenResults codegenResults);
4447

4548
/// Creates the [SsaBuilder] used for the element model.
4649
SsaBuilder createSsaBuilder(
@@ -55,4 +58,15 @@ abstract class BackendStrategy {
5558
/// Creates the [TypesInferrer] used by this strategy.
5659
TypesInferrer createTypesInferrer(
5760
JClosedWorld closedWorld, InferredDataBuilder inferredDataBuilder);
61+
62+
/// Calls [f] for every member that needs to be serialized for modular code
63+
/// generation and returns an [EntityWriter] for encoding these members in
64+
/// the serialized data.
65+
///
66+
/// The needed members include members computed on demand during non-modular
67+
/// code generation, such as constructor bodies and and generator bodies.
68+
EntityWriter forEachCodegenMember(void Function(MemberEntity member) f);
69+
70+
/// Prepare [source] to deserialize modular code generation data.
71+
void prepareCodegenReader(DataSource source);
5872
}

pkg/compiler/lib/src/commandline_options.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ class Flags {
8484
static const String dillDependencies = '--dill-dependencies';
8585
static const String readData = '--read-data';
8686
static const String writeData = '--write-data';
87+
static const String readCodegen = '--read-codegen';
88+
static const String writeCodegen = '--write-codegen';
89+
static const String codegenShard = '--codegen-shard';
90+
static const String codegenShards = '--codegen-shards';
8791
static const String cfeOnly = '--cfe-only';
8892
static const String debugGlobalInference = '--debug-global-inference';
8993

pkg/compiler/lib/src/common/codegen.dart

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,22 @@ library dart2js.common.codegen;
66

77
import 'package:js_ast/src/precedence.dart' as js show PRIMARY;
88

9+
import '../common.dart';
910
import '../common_elements.dart';
1011
import '../constants/values.dart';
1112
import '../deferred_load.dart';
1213
import '../elements/entities.dart';
1314
import '../elements/types.dart' show DartType, InterfaceType;
1415
import '../inferrer/abstract_value_domain.dart';
16+
import '../inferrer/types.dart';
1517
import '../io/source_information.dart';
1618
import '../js/js.dart' as js;
19+
import '../js_backend/backend.dart';
1720
import '../js_backend/namer.dart';
1821
import '../js_emitter/code_emitter_task.dart' show Emitter;
1922
import '../native/behavior.dart';
2023
import '../serialization/serialization.dart';
24+
import '../ssa/ssa.dart';
2125
import '../universe/feature.dart';
2226
import '../universe/selector.dart';
2327
import '../universe/use.dart' show ConstantUse, DynamicUse, StaticUse, TypeUse;
@@ -414,6 +418,58 @@ class CodegenRegistry {
414418
}
415419
}
416420

421+
/// Interface for reading the code generation results for all [MemberEntity]s.
422+
abstract class CodegenResults {
423+
GlobalTypeInferenceResults get globalTypeInferenceResults;
424+
CodegenInputs get codegenInputs;
425+
CodegenResult getCodegenResults(MemberEntity member);
426+
}
427+
428+
/// Code generation results computed on-demand.
429+
///
430+
/// This is used in the non-modular codegen enqueuer driving code generation.
431+
class OnDemandCodegenResults extends CodegenResults {
432+
@override
433+
final GlobalTypeInferenceResults globalTypeInferenceResults;
434+
@override
435+
final CodegenInputs codegenInputs;
436+
final SsaFunctionCompiler _functionCompiler;
437+
438+
OnDemandCodegenResults(this.globalTypeInferenceResults, this.codegenInputs,
439+
this._functionCompiler);
440+
441+
@override
442+
CodegenResult getCodegenResults(MemberEntity member) {
443+
return _functionCompiler.compile(member);
444+
}
445+
}
446+
447+
/// Deserialized code generation results.
448+
///
449+
/// This is used for modular code generation.
450+
class DeserializedCodegenResults extends CodegenResults {
451+
@override
452+
final GlobalTypeInferenceResults globalTypeInferenceResults;
453+
@override
454+
final CodegenInputs codegenInputs;
455+
456+
final Map<MemberEntity, CodegenResult> _map;
457+
458+
DeserializedCodegenResults(
459+
this.globalTypeInferenceResults, this.codegenInputs, this._map);
460+
461+
@override
462+
CodegenResult getCodegenResults(MemberEntity member) {
463+
CodegenResult result = _map[member];
464+
if (result == null) {
465+
failedAt(member,
466+
"No codegen results from $member (${identityHashCode(member)}).");
467+
}
468+
return result;
469+
}
470+
}
471+
472+
/// The code generation result for a single [MemberEntity].
417473
class CodegenResult {
418474
static const String tag = 'codegen-result';
419475

pkg/compiler/lib/src/compiler.dart

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import 'package:front_end/src/api_unstable/dart2js.dart'
1111

1212
import '../compiler_new.dart' as api;
1313
import 'backend_strategy.dart';
14+
import 'common/codegen.dart';
1415
import 'common/names.dart' show Selectors, Uris;
1516
import 'common/tasks.dart' show CompilerTask, GenericTask, Measurer;
1617
import 'common/work.dart' show WorkItem;
@@ -171,7 +172,8 @@ abstract class Compiler {
171172
enqueuer,
172173
dumpInfoTask = new DumpInfoTask(this),
173174
selfTask,
174-
serializationTask = new SerializationTask(this, measurer),
175+
serializationTask = new SerializationTask(
176+
options, reporter, provider, outputProvider, measurer),
175177
];
176178

177179
tasks.addAll(backend.tasks);
@@ -227,13 +229,14 @@ abstract class Compiler {
227229
reporter.log('Compiling $uri (${options.buildId})');
228230

229231
if (options.readDataUri != null) {
230-
GlobalTypeInferenceResults results =
231-
await serializationTask.deserialize();
232+
GlobalTypeInferenceResults globalTypeInferenceResults =
233+
await serializationTask.deserializeGlobalTypeInference(
234+
environment, abstractValueStrategy);
232235
if (options.debugGlobalInference) {
233-
performGlobalTypeInference(results.closedWorld);
236+
performGlobalTypeInference(globalTypeInferenceResults.closedWorld);
234237
return;
235238
}
236-
emitJavaScriptCode(results);
239+
await generateJavaScriptCode(globalTypeInferenceResults);
237240
} else {
238241
KernelResult result = await kernelLoader.load(uri);
239242
reporter.log("Kernel load complete");
@@ -263,6 +266,31 @@ abstract class Compiler {
263266
}
264267
}
265268

269+
void generateJavaScriptCode(
270+
GlobalTypeInferenceResults globalTypeInferenceResults) async {
271+
JClosedWorld closedWorld = globalTypeInferenceResults.closedWorld;
272+
backendStrategy.registerJClosedWorld(closedWorld);
273+
if (options.showInternalProgress) reporter.log('Compiling...');
274+
phase = PHASE_COMPILING;
275+
CodegenInputs codegenInputs =
276+
backend.onCodegenStart(globalTypeInferenceResults);
277+
278+
if (options.readCodegenUri != null) {
279+
CodegenResults codegenResults =
280+
await serializationTask.deserializeCodegen(
281+
backendStrategy, globalTypeInferenceResults, codegenInputs);
282+
runCodegenEnqueuer(codegenResults);
283+
} else {
284+
CodegenResults codegenResults = new OnDemandCodegenResults(
285+
globalTypeInferenceResults, codegenInputs, backend.functionCompiler);
286+
if (options.writeCodegenUri != null) {
287+
serializationTask.serializeCodegen(backendStrategy, codegenResults);
288+
} else {
289+
runCodegenEnqueuer(codegenResults);
290+
}
291+
}
292+
}
293+
266294
/// Clear the internal compiler state to prevent memory leaks when invoking
267295
/// the compiler multiple times (e.g. in batch mode).
268296
// TODO(ahe): implement a better mechanism where we can store
@@ -355,15 +383,13 @@ abstract class Compiler {
355383
mainFunction, closedWorld, inferredDataBuilder);
356384
}
357385

358-
void emitJavaScriptCode(GlobalTypeInferenceResults globalInferenceResults) {
386+
void runCodegenEnqueuer(CodegenResults codegenResults) {
387+
GlobalTypeInferenceResults globalInferenceResults =
388+
codegenResults.globalTypeInferenceResults;
359389
JClosedWorld closedWorld = globalInferenceResults.closedWorld;
360-
backendStrategy.registerJClosedWorld(closedWorld);
361-
if (options.showInternalProgress) reporter.log('Compiling...');
362-
phase = PHASE_COMPILING;
363-
364-
CodegenInputs codegen = backend.onCodegenStart(globalInferenceResults);
390+
CodegenInputs codegenInputs = codegenResults.codegenInputs;
365391
Enqueuer codegenEnqueuer = enqueuer.createCodegenEnqueuer(
366-
closedWorld, globalInferenceResults, codegen);
392+
closedWorld, globalInferenceResults, codegenInputs, codegenResults);
367393
_codegenWorldBuilder = codegenEnqueuer.worldBuilder;
368394

369395
FunctionEntity mainFunction = closedWorld.elementEnvironment.mainFunction;
@@ -375,14 +401,14 @@ abstract class Compiler {
375401
codegenWorldForTesting = codegenWorld;
376402
}
377403
int programSize = backend.assembleProgram(closedWorld,
378-
globalInferenceResults.inferredData, codegen, codegenWorld);
404+
globalInferenceResults.inferredData, codegenInputs, codegenWorld);
379405

380406
if (options.dumpInfo) {
381407
dumpInfoTask.reportSize(programSize);
382408
dumpInfoTask.dumpInfo(closedWorld, globalInferenceResults);
383409
}
384410

385-
backend.onCodegenEnd(codegen);
411+
backend.onCodegenEnd(codegenInputs);
386412

387413
checkQueue(codegenEnqueuer);
388414
}
@@ -397,7 +423,8 @@ abstract class Compiler {
397423
GlobalTypeInferenceResults globalInferenceResults =
398424
performGlobalTypeInference(closedWorld);
399425
if (options.writeDataUri != null) {
400-
serializationTask.serialize(globalInferenceResults);
426+
serializationTask
427+
.serializeGlobalTypeInference(globalInferenceResults);
401428
return;
402429
}
403430
if (options.testMode) {
@@ -415,7 +442,7 @@ abstract class Compiler {
415442
worldData);
416443
}
417444
if (stopAfterTypeInference) return;
418-
emitJavaScriptCode(globalInferenceResults);
445+
generateJavaScriptCode(globalInferenceResults);
419446
}
420447
});
421448
}

0 commit comments

Comments
 (0)