Introduce Codegen interface to decouple JavaScriptBackend from the codegen phase
Change-Id: I7effc20d34fa5d5da799c690182eb6f09948c6ff
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/101288
Reviewed-by: Sigmund Cherem <sigmund@google.com>
diff --git a/pkg/compiler/lib/src/backend_strategy.dart b/pkg/compiler/lib/src/backend_strategy.dart
index c5cfe60..a3461a8 100644
--- a/pkg/compiler/lib/src/backend_strategy.dart
+++ b/pkg/compiler/lib/src/backend_strategy.dart
@@ -43,7 +43,7 @@
GlobalTypeInferenceResults globalInferenceResults);
/// Creates the [SsaBuilder] used for the element model.
- SsaBuilder createSsaBuilder(CompilerTask task, JavaScriptBackend backend,
+ SsaBuilder createSsaBuilder(CompilerTask task, CodegenInputs codegen,
SourceInformationStrategy sourceInformationStrategy);
/// Returns the [SourceInformationStrategy] use for the element model.
diff --git a/pkg/compiler/lib/src/common/codegen.dart b/pkg/compiler/lib/src/common/codegen.dart
index ec92751..b2dedea 100644
--- a/pkg/compiler/lib/src/common/codegen.dart
+++ b/pkg/compiler/lib/src/common/codegen.dart
@@ -7,6 +7,7 @@
import '../common_elements.dart';
import '../elements/entities.dart';
import '../elements/types.dart' show DartType, InterfaceType;
+import '../native/behavior.dart';
import '../universe/feature.dart';
import '../universe/use.dart' show ConstantUse, DynamicUse, StaticUse, TypeUse;
import '../universe/world_impact.dart'
@@ -34,6 +35,10 @@
Iterable<GenericInstantiation> get genericInstantiations =>
const <GenericInstantiation>[];
+
+ Iterable<NativeBehavior> get nativeBehaviors => const [];
+
+ Iterable<FunctionEntity> get nativeMethods => const [];
}
class _CodegenImpact extends WorldImpactBuilderImpl implements CodegenImpact {
@@ -43,6 +48,8 @@
bool _usesInterceptor = false;
EnumSet<AsyncMarker> _asyncMarkers;
Set<GenericInstantiation> _genericInstantiations;
+ List<NativeBehavior> _nativeBehaviors;
+ Set<FunctionEntity> _nativeMethods;
_CodegenImpact();
@@ -117,6 +124,26 @@
Iterable<GenericInstantiation> get genericInstantiations {
return _genericInstantiations ?? const <GenericInstantiation>[];
}
+
+ void registerNativeBehavior(NativeBehavior nativeBehavior) {
+ _nativeBehaviors ??= [];
+ _nativeBehaviors.add(nativeBehavior);
+ }
+
+ @override
+ Iterable<NativeBehavior> get nativeBehaviors {
+ return _nativeBehaviors ?? const <NativeBehavior>[];
+ }
+
+ void registerNativeMethod(FunctionEntity function) {
+ _nativeMethods ??= {};
+ _nativeMethods.add(function);
+ }
+
+ @override
+ Iterable<FunctionEntity> get nativeMethods {
+ return _nativeMethods ?? const [];
+ }
}
// TODO(johnniwinther): Split this class into interface and implementation.
@@ -187,6 +214,14 @@
void registerGenericInstantiation(GenericInstantiation instantiation) {
worldImpact.registerGenericInstantiation(instantiation);
}
+
+ void registerNativeBehavior(NativeBehavior nativeBehavior) {
+ worldImpact.registerNativeBehavior(nativeBehavior);
+ }
+
+ void registerNativeMethod(FunctionEntity function) {
+ worldImpact.registerNativeMethod(function);
+ }
}
/// [WorkItem] used exclusively by the [CodegenEnqueuer].
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index 3bfb460..eec68ab 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -204,7 +204,7 @@
classInfo.size = size;
- if (!compiler.backend.emitter.neededClasses.contains(clazz) &&
+ if (!compiler.backend.emitterTask.neededClasses.contains(clazz) &&
classInfo.fields.isEmpty &&
classInfo.functions.isEmpty) {
return null;
@@ -350,7 +350,7 @@
? compiler.options.outputUri.pathSegments.last
: deferredPartFileName(compiler.options, outputUnit.name);
OutputUnitInfo info = new OutputUnitInfo(filename, outputUnit.name,
- backend.emitter.emitter.generatedSize(outputUnit));
+ backend.emitterTask.emitter.generatedSize(outputUnit));
info.imports
.addAll(closedWorld.outputUnitData.getImportNames(outputUnit));
result.outputUnits.add(info);
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index 026dd8c1..ffb0c40 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -6,36 +6,30 @@
import '../common.dart';
import '../common/backend_api.dart' show ImpactTransformer;
-import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
+import '../common/codegen.dart' show CodegenWorkItem;
import '../common/names.dart' show Uris;
import '../common/tasks.dart' show CompilerTask;
-import '../common_elements.dart'
- show CommonElements, ElementEnvironment, JElementEnvironment;
+import '../common_elements.dart' show CommonElements, ElementEnvironment;
import '../compiler.dart' show Compiler;
import '../deferred_load.dart' show DeferredLoadTask;
import '../dump_info.dart' show DumpInfoTask;
import '../elements/entities.dart';
-import '../elements/types.dart';
import '../enqueue.dart' show Enqueuer, EnqueueTask, ResolutionEnqueuer;
import '../frontend_strategy.dart';
import '../inferrer/types.dart';
-import '../io/source_information.dart'
- show SourceInformation, SourceInformationStrategy;
+import '../io/source_information.dart' show SourceInformationStrategy;
import '../js/js.dart' as jsAst;
import '../js_model/elements.dart';
-import '../js/rewrite_async.dart';
-import '../js_emitter/js_emitter.dart' show CodeEmitterTask;
+import '../js_emitter/js_emitter.dart' show CodeEmitterTask, Emitter;
import '../js_emitter/sorter.dart' show Sorter;
import '../kernel/dart2js_target.dart';
import '../native/enqueue.dart';
import '../ssa/ssa.dart' show SsaFunctionCompiler;
import '../tracer.dart';
-import '../universe/call_structure.dart' show CallStructure;
import '../universe/class_hierarchy.dart'
show ClassHierarchyBuilder, ClassQueries;
import '../universe/codegen_world_builder.dart';
import '../universe/selector.dart' show Selector;
-import '../universe/use.dart' show StaticUse;
import '../universe/world_builder.dart';
import '../universe/world_impact.dart'
show ImpactStrategy, ImpactUseCase, WorldImpact, WorldImpactVisitor;
@@ -59,10 +53,13 @@
import 'runtime_types.dart';
abstract class FunctionCompiler {
- void onCodegenStart();
+ void onCodegenStart(CodegenInputs codegen);
/// Generates JavaScript code for `work.element`.
- jsAst.Fun compile(CodegenWorkItem work, JClosedWorld closedWorld,
+ jsAst.Fun compile(
+ CodegenWorkItem work,
+ CodegenInputs codegen,
+ JClosedWorld closedWorld,
GlobalTypeInferenceResults globalInferenceResults);
Iterable get tasks;
@@ -295,7 +292,7 @@
NAME
}
-class JavaScriptBackend {
+class JavaScriptBackend implements CodegenInputs {
static const String JS = 'JS';
static const String JS_BUILTIN = 'JS_BUILTIN';
static const String JS_EMBEDDED_GLOBAL = 'JS_EMBEDDED_GLOBAL';
@@ -308,7 +305,10 @@
FunctionCompiler functionCompiler;
- CodeEmitterTask emitter;
+ CodeEmitterTask emitterTask;
+
+ @override
+ Emitter get emitter => emitterTask.emitter;
/// The generated code as a js AST for compiled methods.
final Map<MemberEntity, jsAst.Expression> generatedCode =
@@ -316,6 +316,7 @@
Namer _namer;
+ @override
Namer get namer {
assert(_namer != null,
failedAt(NO_LOCATION_SPANNABLE, "Namer has not been created yet."));
@@ -327,7 +328,7 @@
List<CompilerTask> get tasks {
List<CompilerTask> result = functionCompiler.tasks;
- result.add(emitter);
+ result.add(emitterTask);
return result;
}
@@ -368,11 +369,13 @@
CheckedModeHelpers _checkedModeHelpers;
+ @override
final SuperMemberData superMemberData = new SuperMemberData();
NativeResolutionEnqueuer _nativeResolutionEnqueuer;
NativeCodegenEnqueuer _nativeCodegenEnqueuer;
+ @override
Tracer tracer;
JavaScriptBackend(this.compiler,
@@ -385,11 +388,15 @@
_backendUsageBuilder =
new BackendUsageBuilderImpl(compiler.frontendStrategy);
_checkedModeHelpers = new CheckedModeHelpers();
- emitter = new CodeEmitterTask(compiler, generateSourceMap);
+ emitterTask = new CodeEmitterTask(compiler, generateSourceMap);
noSuchMethodRegistry = new NoSuchMethodRegistryImpl(
commonElements, compiler.frontendStrategy.createNoSuchMethodResolver());
functionCompiler = new SsaFunctionCompiler(
- this, compiler.measurer, sourceInformationStrategy);
+ compiler.options,
+ compiler.reporter,
+ compiler.backendStrategy,
+ compiler.measurer,
+ sourceInformationStrategy);
}
DiagnosticReporter get reporter => compiler.reporter;
@@ -418,6 +425,7 @@
return _customElementsCodegenAnalysis;
}
+ @override
OneShotInterceptorData get oneShotInterceptorData {
assert(
_oneShotInterceptorData != null,
@@ -440,6 +448,7 @@
RuntimeTypesChecksBuilder get rtiChecksBuilderForTesting => _rtiChecksBuilder;
+ @override
RuntimeTypesSubstitutions get rtiSubstitutions {
assert(
_rtiSubstitutions != null,
@@ -448,6 +457,7 @@
return _rtiSubstitutions;
}
+ @override
RuntimeTypesEncoder get rtiEncoder {
assert(
_rtiEncoder != null,
@@ -456,6 +466,7 @@
return _rtiEncoder;
}
+ @override
CheckedModeHelpers get checkedModeHelpers => _checkedModeHelpers;
Namer determineNamer(JClosedWorld closedWorld) {
@@ -605,7 +616,7 @@
elementEnvironment,
commonElements,
closedWorld.dartTypes,
- emitter,
+ emitterTask,
closedWorld.liveNativeClasses,
closedWorld.nativeData);
return new CodegenEnqueuer(
@@ -638,8 +649,8 @@
return const WorldImpact();
}
- jsAst.Fun function =
- functionCompiler.compile(work, closedWorld, globalInferenceResults);
+ jsAst.Fun function = functionCompiler.compile(
+ work, this, closedWorld, globalInferenceResults);
if (function != null) {
if (function.sourceInformation == null) {
function = function.withSourceInformation(
@@ -673,8 +684,8 @@
/// Generates the output and returns the total size of the generated code.
int assembleProgram(JClosedWorld closedWorld, InferredData inferredData,
CodegenWorld codegenWorld) {
- int programSize =
- emitter.assembleProgram(namer, closedWorld, inferredData, codegenWorld);
+ int programSize = emitterTask.assembleProgram(
+ namer, closedWorld, inferredData, codegenWorld);
closedWorld.noSuchMethodData.emitDiagnostic(reporter);
return programSize;
}
@@ -698,7 +709,6 @@
/// [WorldImpact] of enabled backend features is returned.
WorldImpact onCodegenStart(JClosedWorld closedWorld,
CodegenWorldBuilder codegenWorldBuilder, Sorter sorter) {
- functionCompiler.onCodegenStart();
_oneShotInterceptorData = new OneShotInterceptorData(
closedWorld.interceptorData, closedWorld.commonElements);
_namer = determineNamer(closedWorld);
@@ -709,7 +719,7 @@
closedWorld.elementEnvironment,
closedWorld.commonElements,
closedWorld.rtiNeed);
- emitter.createEmitter(namer, closedWorld, codegenWorldBuilder, sorter);
+ emitterTask.createEmitter(namer, closedWorld, codegenWorldBuilder, sorter);
// TODO(johnniwinther): Share the impact object created in
// createCodegenEnqueuer.
BackendImpacts impacts = new BackendImpacts(closedWorld.commonElements);
@@ -734,7 +744,10 @@
nativeCodegenEnqueuer,
namer,
oneShotInterceptorData,
- rtiChecksBuilder);
+ rtiChecksBuilder,
+ emitterTask.nativeEmitter);
+
+ functionCompiler.onCodegenStart(this);
return const WorldImpact();
}
@@ -744,117 +757,6 @@
tracer.close();
}
- jsAst.Expression rewriteAsync(
- CommonElements commonElements,
- JElementEnvironment elementEnvironment,
- CodegenRegistry registry,
- FunctionEntity element,
- jsAst.Expression code,
- DartType asyncTypeParameter,
- SourceInformation bodySourceInformation,
- SourceInformation exitSourceInformation) {
- if (element.asyncMarker == AsyncMarker.SYNC) return code;
-
- AsyncRewriterBase rewriter = null;
- jsAst.Name name = namer.methodPropertyName(
- element is JGeneratorBody ? element.function : element);
-
- switch (element.asyncMarker) {
- case AsyncMarker.ASYNC:
- rewriter = _makeAsyncRewriter(commonElements, elementEnvironment,
- registry, element, code, asyncTypeParameter, name);
- break;
- case AsyncMarker.SYNC_STAR:
- rewriter = new SyncStarRewriter(reporter, element,
- endOfIteration:
- emitter.staticFunctionAccess(commonElements.endOfIteration),
- iterableFactory: emitter
- .staticFunctionAccess(commonElements.syncStarIterableFactory),
- iterableFactoryTypeArguments: _fetchItemType(asyncTypeParameter),
- yieldStarExpression:
- emitter.staticFunctionAccess(commonElements.yieldStar),
- uncaughtErrorExpression: emitter
- .staticFunctionAccess(commonElements.syncStarUncaughtError),
- safeVariableName: namer.safeVariablePrefixForAsyncRewrite,
- bodyName: namer.deriveAsyncBodyName(name));
- registry.registerStaticUse(new StaticUse.staticInvoke(
- commonElements.syncStarIterableFactory,
- const CallStructure.unnamed(1, 1), [
- elementEnvironment.getFunctionAsyncOrSyncStarElementType(element)
- ]));
- break;
- case AsyncMarker.ASYNC_STAR:
- rewriter = new AsyncStarRewriter(reporter, element,
- asyncStarHelper:
- emitter.staticFunctionAccess(commonElements.asyncStarHelper),
- streamOfController:
- emitter.staticFunctionAccess(commonElements.streamOfController),
- wrapBody: emitter.staticFunctionAccess(commonElements.wrapBody),
- newController: emitter.staticFunctionAccess(
- commonElements.asyncStarStreamControllerFactory),
- newControllerTypeArguments: _fetchItemType(asyncTypeParameter),
- safeVariableName: namer.safeVariablePrefixForAsyncRewrite,
- yieldExpression:
- emitter.staticFunctionAccess(commonElements.yieldSingle),
- yieldStarExpression:
- emitter.staticFunctionAccess(commonElements.yieldStar),
- bodyName: namer.deriveAsyncBodyName(name));
- registry.registerStaticUse(new StaticUse.staticInvoke(
- commonElements.asyncStarStreamControllerFactory,
- const CallStructure.unnamed(1, 1), [
- elementEnvironment.getFunctionAsyncOrSyncStarElementType(element)
- ]));
- break;
- }
- return rewriter.rewrite(code, bodySourceInformation, exitSourceInformation);
- }
-
- /// Returns an optional expression that evaluates [type]. Returns `null` if
- /// the type expression is determined by the outside context and should be
- /// added as a function parameter to the rewritten code.
- // TODO(sra): We could also return an empty list if the generator takes no
- // type (e.g. due to rtiNeed optimization).
- List<jsAst.Expression> _fetchItemType(DartType type) {
- if (type == null) return null;
- var ast = rtiEncoder.getTypeRepresentation(emitter.emitter, type, null);
- return <jsAst.Expression>[ast];
- }
-
- AsyncRewriter _makeAsyncRewriter(
- CommonElements commonElements,
- JElementEnvironment elementEnvironment,
- CodegenRegistry registry,
- FunctionEntity element,
- jsAst.Expression code,
- DartType elementType,
- jsAst.Name name) {
- var startFunction = commonElements.asyncHelperStartSync;
- var completerFactory = commonElements.asyncAwaitCompleterFactory;
-
- List<jsAst.Expression> itemTypeExpression = _fetchItemType(elementType);
-
- var rewriter = new AsyncRewriter(reporter, element,
- asyncStart: emitter.staticFunctionAccess(startFunction),
- asyncAwait:
- emitter.staticFunctionAccess(commonElements.asyncHelperAwait),
- asyncReturn:
- emitter.staticFunctionAccess(commonElements.asyncHelperReturn),
- asyncRethrow:
- emitter.staticFunctionAccess(commonElements.asyncHelperRethrow),
- wrapBody: emitter.staticFunctionAccess(commonElements.wrapBody),
- completerFactory: emitter.staticFunctionAccess(completerFactory),
- completerFactoryTypeArguments: itemTypeExpression,
- safeVariableName: namer.safeVariablePrefixForAsyncRewrite,
- bodyName: namer.deriveAsyncBodyName(name));
-
- registry.registerStaticUse(new StaticUse.staticInvoke(
- completerFactory,
- const CallStructure.unnamed(0, 1),
- [elementEnvironment.getFunctionAsyncOrSyncStarElementType(element)]));
-
- return rewriter;
- }
-
/// Creates an impact strategy to use for compilation.
ImpactStrategy createImpactStrategy(
{bool supportDeferredLoad: true, bool supportDumpInfo: true}) {
@@ -929,3 +831,20 @@
return _aliasedSuperMembers.contains(member);
}
}
+
+/// Interface for resources only used during code generation.
+///
+/// This is currently implemented by the [JavaScriptBackend] but should be
+/// a separate object created when the codegen phase starts.
+abstract class CodegenInputs {
+ // TODO(johnniwinther): Should be the modular part of the emitter.
+ Emitter get emitter;
+ CheckedModeHelpers get checkedModeHelpers;
+ OneShotInterceptorData get oneShotInterceptorData;
+ RuntimeTypesSubstitutions get rtiSubstitutions;
+ RuntimeTypesEncoder get rtiEncoder;
+ // TODO(johnniwinther): Should be the modular part of the namer.
+ Namer get namer;
+ SuperMemberData get superMemberData;
+ Tracer get tracer;
+}
diff --git a/pkg/compiler/lib/src/js_backend/constant_emitter.dart b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
index f214ed2..8976841 100644
--- a/pkg/compiler/lib/src/js_backend/constant_emitter.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
@@ -320,7 +320,7 @@
@override
jsAst.Expression visitInterceptor(InterceptorConstantValue constant, [_]) {
ClassEntity interceptorClass = constant.cls;
- return _task.interceptorPrototypeAccess(interceptorClass);
+ return _emitter.interceptorPrototypeAccess(interceptorClass);
}
@override
diff --git a/pkg/compiler/lib/src/js_backend/impact_transformer.dart b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
index 1dbffb7..d4276ff 100644
--- a/pkg/compiler/lib/src/js_backend/impact_transformer.dart
+++ b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
@@ -15,6 +15,7 @@
import '../constants/expressions.dart';
import '../elements/entities.dart';
import '../elements/types.dart';
+import '../js_emitter/native_emitter.dart';
import '../native/enqueue.dart';
import '../native/behavior.dart';
import '../options.dart';
@@ -351,6 +352,7 @@
final Namer _namer;
final OneShotInterceptorData _oneShotInterceptorData;
final RuntimeTypesChecksBuilder _rtiChecksBuilder;
+ final NativeEmitter _nativeEmitter;
CodegenImpactTransformer(
this._options,
@@ -363,7 +365,8 @@
this._nativeCodegenEnqueuer,
this._namer,
this._oneShotInterceptorData,
- this._rtiChecksBuilder);
+ this._rtiChecksBuilder,
+ this._nativeEmitter);
void onIsCheckForCodegen(DartType type, TransformedWorldImpact transformed) {
if (type.isDynamic) return;
@@ -443,6 +446,15 @@
_rtiChecksBuilder.registerGenericInstantiation(instantiation);
}
+ for (NativeBehavior behavior in impact.nativeBehaviors) {
+ _nativeCodegenEnqueuer.registerNativeBehavior(
+ transformed, behavior, impact);
+ }
+
+ for (FunctionEntity function in impact.nativeMethods) {
+ _nativeEmitter.nativeMethods.add(function);
+ }
+
// TODO(johnniwinther): Remove eager registration.
return transformed;
}
diff --git a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
index b59b9f2..5e7d7a5 100644
--- a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
+++ b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
@@ -73,73 +73,6 @@
/// Returns true, if the emitter supports reflection.
bool get supportsReflection => _emitterFactory.supportsReflection;
- /// Returns the closure expression of a static function.
- jsAst.Expression isolateStaticClosureAccess(FunctionEntity element) {
- return emitter.isolateStaticClosureAccess(element);
- }
-
- /// Returns the JS function that must be invoked to get the value of the
- /// lazily initialized static.
- jsAst.Expression isolateLazyInitializerAccess(FieldEntity element) {
- return emitter.isolateLazyInitializerAccess(element);
- }
-
- /// Returns the JS code for accessing the embedded [global].
- jsAst.Expression generateEmbeddedGlobalAccess(String global) {
- return emitter.generateEmbeddedGlobalAccess(global);
- }
-
- /// Returns the JS code for accessing the given [constant].
- jsAst.Expression constantReference(ConstantValue constant) {
- return emitter.constantReference(constant);
- }
-
- jsAst.Expression staticFieldAccess(FieldEntity e) {
- return emitter.staticFieldAccess(e);
- }
-
- /// Returns the JS function representing the given function.
- ///
- /// The function must be invoked and can not be used as closure.
- jsAst.Expression staticFunctionAccess(FunctionEntity e) {
- return emitter.staticFunctionAccess(e);
- }
-
- /// Returns the JS constructor of the given element.
- ///
- /// The returned expression must only be used in a JS `new` expression.
- jsAst.Expression constructorAccess(ClassEntity e) {
- return emitter.constructorAccess(e);
- }
-
- /// Returns the JS prototype of the given class [e].
- jsAst.Expression prototypeAccess(ClassEntity e,
- {bool hasBeenInstantiated: false}) {
- return emitter.prototypeAccess(e, hasBeenInstantiated);
- }
-
- /// Returns the JS prototype of the given interceptor class [e].
- jsAst.Expression interceptorPrototypeAccess(ClassEntity e) {
- return jsAst.js('#.prototype', interceptorClassAccess(e));
- }
-
- /// Returns the JS constructor of the given interceptor class [e].
- jsAst.Expression interceptorClassAccess(ClassEntity e) {
- return emitter.interceptorClassAccess(e);
- }
-
- /// Returns the JS expression representing the type [e].
- ///
- /// The given type [e] might be a Typedef.
- jsAst.Expression typeAccess(Entity e) {
- return emitter.typeAccess(e);
- }
-
- /// Returns the JS template for the given [builtin].
- jsAst.Template builtinTemplateFor(JsBuiltin builtin) {
- return emitter.templateForBuiltin(builtin);
- }
-
void _finalizeRti(CodegenWorld codegenWorld) {
// Compute the required type checks to know which classes need a
// 'is$' method.
@@ -247,8 +180,10 @@
jsAst.Expression constructorAccess(ClassEntity e);
/// Returns the JS prototype of the given class [e].
- jsAst.Expression prototypeAccess(
- covariant ClassEntity e, bool hasBeenInstantiated);
+ jsAst.Expression prototypeAccess(ClassEntity e, {bool hasBeenInstantiated});
+
+ /// Returns the JS prototype of the given interceptor class [e].
+ jsAst.Expression interceptorPrototypeAccess(ClassEntity e);
/// Returns the JS constructor of the given interceptor class [e].
jsAst.Expression interceptorClassAccess(ClassEntity e);
diff --git a/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
index a826fe9..eeecd6ff 100644
--- a/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
@@ -23,12 +23,12 @@
import '../universe/selector.dart' show Selector;
import '../world.dart' show JClosedWorld;
-import 'code_emitter_task.dart' show CodeEmitterTask, Emitter;
+import 'code_emitter_task.dart' show Emitter;
class InterceptorStubGenerator {
final CompilerOptions _options;
final CommonElements _commonElements;
- final CodeEmitterTask _emitterTask;
+ final Emitter _emitter;
final NativeCodegenEnqueuer _nativeCodegenEnqueuer;
final Namer _namer;
final OneShotInterceptorData _oneShotInterceptorData;
@@ -39,7 +39,7 @@
InterceptorStubGenerator(
this._options,
this._commonElements,
- this._emitterTask,
+ this._emitter,
this._nativeCodegenEnqueuer,
this._namer,
this._oneShotInterceptorData,
@@ -51,11 +51,9 @@
InterceptorData get _interceptorData => _closedWorld.interceptorData;
- Emitter get _emitter => _emitterTask.emitter;
-
jsAst.Expression generateGetInterceptorMethod(Set<ClassEntity> classes) {
jsAst.Expression interceptorFor(ClassEntity cls) {
- return _emitterTask.interceptorPrototypeAccess(cls);
+ return _emitter.interceptorPrototypeAccess(cls);
}
/// Build a JavaScript AST node for doing a type check on
diff --git a/pkg/compiler/lib/src/js_emitter/native_emitter.dart b/pkg/compiler/lib/src/js_emitter/native_emitter.dart
index 5836b24..7be3f0d 100644
--- a/pkg/compiler/lib/src/js_emitter/native_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/native_emitter.dart
@@ -269,7 +269,7 @@
if (stubParameter.name == name) {
type = type.unaliased;
if (type.isFunctionType) {
- closureConverter ??= _emitterTask
+ closureConverter ??= _emitterTask.emitter
.staticFunctionAccess(_commonElements.closureConverter);
// The parameter type is a function type either directly or through
diff --git a/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
index e57d145..14ae576 100644
--- a/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
@@ -23,12 +23,14 @@
import 'model.dart';
-import 'code_emitter_task.dart' show CodeEmitterTask, Emitter;
+import 'code_emitter_task.dart' show Emitter;
+import 'native_emitter.dart';
class ParameterStubGenerator {
static final Set<Selector> emptySelectorSet = new Set<Selector>();
- final CodeEmitterTask _emitterTask;
+ final Emitter _emitter;
+ final NativeEmitter _nativeEmitter;
final Namer _namer;
final RuntimeTypesEncoder _rtiEncoder;
final NativeData _nativeData;
@@ -38,7 +40,8 @@
final SourceInformationStrategy _sourceInformationStrategy;
ParameterStubGenerator(
- this._emitterTask,
+ this._emitter,
+ this._nativeEmitter,
this._namer,
this._rtiEncoder,
this._nativeData,
@@ -47,8 +50,6 @@
this._closedWorld,
this._sourceInformationStrategy);
- Emitter get _emitter => _emitterTask.emitter;
-
JElementEnvironment get _elementEnvironment =>
_closedWorld.elementEnvironment;
@@ -190,7 +191,7 @@
var body; // List or jsAst.Statement.
if (_nativeData.hasFixedBackendName(member)) {
- body = _emitterTask.nativeEmitter.generateParameterStubStatements(
+ body = _nativeEmitter.generateParameterStubStatements(
member,
isInterceptedMethod,
_namer.invocationName(selector),
@@ -206,7 +207,7 @@
// Instead we need to call the statically resolved target.
// `<class>.prototype.bar$1.call(this, argument0, ...)`.
body = js.statement('return #.#.call(this, #);', [
- _emitterTask.prototypeAccess(superClass, hasBeenInstantiated: true),
+ _emitter.prototypeAccess(superClass, hasBeenInstantiated: true),
methodName,
targetArguments
]);
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
index 3eb330e..cd297c8 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
@@ -342,7 +342,7 @@
InterceptorStubGenerator stubGenerator = new InterceptorStubGenerator(
_options,
_commonElements,
- _task,
+ _task.emitter,
_nativeCodegenEnqueuer,
_namer,
_oneShotInterceptorData,
@@ -969,7 +969,8 @@
if (!_methodNeedsStubs(element)) return const <ParameterStubMethod>[];
ParameterStubGenerator generator = new ParameterStubGenerator(
- _task,
+ _task.emitter,
+ _task.nativeEmitter,
_namer,
_rtiEncoder,
_nativeData,
@@ -1015,7 +1016,7 @@
InterceptorStubGenerator stubGenerator = new InterceptorStubGenerator(
_options,
_commonElements,
- _task,
+ _task.emitter,
_nativeCodegenEnqueuer,
_namer,
_oneShotInterceptorData,
@@ -1111,7 +1112,7 @@
InterceptorStubGenerator stubGenerator = new InterceptorStubGenerator(
_options,
_commonElements,
- _task,
+ _task.emitter,
_nativeCodegenEnqueuer,
_namer,
_oneShotInterceptorData,
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
index 546077f..6bf225e 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
@@ -110,14 +110,19 @@
}
@override
- js.PropertyAccess prototypeAccess(
- ClassEntity element, bool hasBeenInstantiated) {
+ js.PropertyAccess prototypeAccess(ClassEntity element,
+ {bool hasBeenInstantiated}) {
js.Expression constructor =
hasBeenInstantiated ? constructorAccess(element) : typeAccess(element);
return js.js('#.prototype', constructor);
}
@override
+ js.Expression interceptorPrototypeAccess(ClassEntity e) {
+ return js.js('#.prototype', interceptorClassAccess(e));
+ }
+
+ @override
js.Template templateForBuiltin(JsBuiltin builtin) {
switch (builtin) {
case JsBuiltin.dartObjectConstructor:
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
index 633e642..1d5c23d 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
@@ -621,11 +621,14 @@
// TODO(29455): 'hunkHelpers' displaces other names, so don't minify it.
'hunkHelpers': js.VariableDeclaration('hunkHelpers', allowRename: false),
'directAccessTestExpression': js.js(directAccessTestExpression),
- 'cyclicThrow': backend.emitter
+ 'cyclicThrow': backend.emitterTask.emitter
.staticFunctionAccess(_closedWorld.commonElements.cyclicThrowHelper),
'operatorIsPrefix': js.string(namer.operatorIsPrefix),
- 'tearOffCode': new js.Block(buildTearOffCode(compiler.options,
- backend.emitter.emitter, backend.namer, _closedWorld.commonElements)),
+ 'tearOffCode': new js.Block(buildTearOffCode(
+ compiler.options,
+ backend.emitterTask.emitter,
+ backend.namer,
+ _closedWorld.commonElements)),
'embeddedTypes': generateEmbeddedGlobalAccess(TYPES),
'embeddedInterceptorTags':
generateEmbeddedGlobalAccess(INTERCEPTORS_BY_TAG),
diff --git a/pkg/compiler/lib/src/js_model/element_map.dart b/pkg/compiler/lib/src/js_model/element_map.dart
index f435fbd..1c7f8f8 100644
--- a/pkg/compiler/lib/src/js_model/element_map.dart
+++ b/pkg/compiler/lib/src/js_model/element_map.dart
@@ -141,8 +141,7 @@
LibraryEntity getLibrary(ir.Library node);
/// Returns the [js.Template] for the `JsBuiltin` [constant] value.
- js.Template getJsBuiltinTemplate(
- ConstantValue constant, CodeEmitterTask emitter);
+ js.Template getJsBuiltinTemplate(ConstantValue constant, Emitter emitter);
/// Returns a [Spannable] for a message pointing to the IR [node] in the
/// context of [member].
diff --git a/pkg/compiler/lib/src/js_model/element_map_impl.dart b/pkg/compiler/lib/src/js_model/element_map_impl.dart
index be39539..30418af 100644
--- a/pkg/compiler/lib/src/js_model/element_map_impl.dart
+++ b/pkg/compiler/lib/src/js_model/element_map_impl.dart
@@ -2111,12 +2111,11 @@
}
@override
- js.Template getJsBuiltinTemplate(
- ConstantValue constant, CodeEmitterTask emitter) {
+ js.Template getJsBuiltinTemplate(ConstantValue constant, Emitter emitter) {
int index = extractEnumIndexFromConstantValue(
constant, commonElements.jsBuiltinEnum);
if (index == null) return null;
- return emitter.builtinTemplateFor(JsBuiltin.values[index]);
+ return emitter.templateForBuiltin(JsBuiltin.values[index]);
}
}
diff --git a/pkg/compiler/lib/src/js_model/js_strategy.dart b/pkg/compiler/lib/src/js_model/js_strategy.dart
index b57bd96..f07e522 100644
--- a/pkg/compiler/lib/src/js_model/js_strategy.dart
+++ b/pkg/compiler/lib/src/js_model/js_strategy.dart
@@ -12,6 +12,7 @@
import '../common/tasks.dart';
import '../compiler.dart';
import '../deferred_load.dart';
+import '../dump_info.dart';
import '../elements/entities.dart';
import '../enqueue.dart';
import '../io/kernel_source_information.dart'
@@ -23,13 +24,17 @@
import '../js/js_source_mapping.dart';
import '../js_backend/backend.dart';
import '../js_backend/inferred_data.dart';
+import '../js_backend/namer.dart';
import '../js_backend/native_data.dart';
+import '../js_emitter/code_emitter_task.dart';
import '../kernel/kernel_strategy.dart';
import '../native/behavior.dart';
+import '../options.dart';
import '../ssa/builder_kernel.dart';
import '../ssa/nodes.dart';
import '../ssa/ssa.dart';
import '../ssa/types.dart';
+import '../tracer.dart';
import '../universe/codegen_world_builder.dart';
import '../universe/selector.dart';
import '../universe/world_builder.dart';
@@ -92,13 +97,19 @@
}
@override
- SsaBuilder createSsaBuilder(CompilerTask task, JavaScriptBackend backend,
+ SsaBuilder createSsaBuilder(CompilerTask task, CodegenInputs codegen,
SourceInformationStrategy sourceInformationStrategy) {
return new KernelSsaBuilder(
task,
- backend.compiler,
+ _compiler.options,
+ _compiler.reporter,
+ _compiler.dumpInfoTask,
// ignore:deprecated_member_use_from_same_package
- elementMap);
+ elementMap,
+ codegen.namer,
+ codegen.emitter,
+ codegen.tracer,
+ sourceInformationStrategy);
}
@override
@@ -167,33 +178,50 @@
/// Task for building SSA from kernel IR loaded from .dill.
class KernelSsaBuilder implements SsaBuilder {
- final CompilerTask task;
- final Compiler _compiler;
+ final CompilerTask _task;
+ final CompilerOptions _options;
+ final DiagnosticReporter _reporter;
+ final DumpInfoTask _dumpInfoTask;
final JsToElementMap _elementMap;
+ final Namer _namer;
+ final Emitter _emitter;
+ final Tracer _tracer;
+ final SourceInformationStrategy _sourceInformationStrategy;
+
+ // TODO(johnniwinther,sra): Inlining decisions should not be based on the
+ // order in which ssa graphs are built.
FunctionInlineCache _inlineCache;
- KernelSsaBuilder(this.task, this._compiler, this._elementMap);
+ KernelSsaBuilder(
+ this._task,
+ this._options,
+ this._reporter,
+ this._dumpInfoTask,
+ this._elementMap,
+ this._namer,
+ this._emitter,
+ this._tracer,
+ this._sourceInformationStrategy);
@override
HGraph build(CodegenWorkItem work, JClosedWorld closedWorld,
GlobalTypeInferenceResults results) {
_inlineCache ??= new FunctionInlineCache(closedWorld.annotationsData);
- return task.measure(() {
+ return _task.measure(() {
KernelSsaGraphBuilder builder = new KernelSsaGraphBuilder(
- _compiler.options,
- _compiler.reporter,
+ _options,
+ _reporter,
work.element,
_elementMap.getMemberThisType(work.element),
- _compiler.dumpInfoTask,
+ _dumpInfoTask,
_elementMap,
results,
closedWorld,
work.registry,
- _compiler.backend.namer,
- _compiler.backend.emitter,
- _compiler.backend.tracer,
- _compiler.backend.emitter.nativeEmitter,
- _compiler.backend.sourceInformationStrategy,
+ _namer,
+ _emitter,
+ _tracer,
+ _sourceInformationStrategy,
_inlineCache);
return builder.build();
});
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 1811d96..2f3ace7a 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -37,7 +37,6 @@
import '../js_backend/native_data.dart';
import '../js_backend/runtime_types.dart';
import '../js_emitter/code_emitter_task.dart';
-import '../js_emitter/js_emitter.dart' show NativeEmitter;
import '../js_model/locals.dart' show JumpVisitor;
import '../js_model/elements.dart' show JGeneratorBody;
import '../js_model/element_map.dart';
@@ -114,7 +113,7 @@
final CompilerOptions options;
final DiagnosticReporter reporter;
- final CodeEmitterTask _emitter;
+ final Emitter _emitter;
final Namer _namer;
final MemberEntity targetElement;
final MemberEntity _initialTargetElement;
@@ -143,8 +142,6 @@
LoopHandler _loopHandler;
TypeBuilder _typeBuilder;
- final NativeEmitter _nativeEmitter;
-
/// True if we are visiting the expression of a throw statement; we assume
/// this is a slow path.
bool _inExpressionOfThrow = false;
@@ -171,7 +168,6 @@
this._namer,
this._emitter,
this._tracer,
- this._nativeEmitter,
this._sourceInformationStrategy,
this._inlineCache)
: this.targetElement = _effectiveTargetElementFor(_initialTargetElement),
@@ -1491,7 +1487,7 @@
parameterStructure: function.parameterStructure);
if (closedWorld.nativeData.isNativeMember(targetElement)) {
- _nativeEmitter.nativeMethods.add(targetElement);
+ registry.registerNativeMethod(targetElement);
String nativeName;
if (closedWorld.nativeData.hasFixedBackendName(targetElement)) {
nativeName = closedWorld.nativeData.getFixedBackendName(targetElement);
@@ -4716,7 +4712,7 @@
HForeignCode _invokeJsInteropFunction(
FunctionEntity element, List<HInstruction> arguments) {
assert(closedWorld.nativeData.isJsInteropMember(element));
- _nativeEmitter.nativeMethods.add(element);
+ registry.registerNativeMethod(element);
if (element is ConstructorEntity &&
element.isFactoryConstructor &&
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index 73e35e3..6bfaa83 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -10,7 +10,7 @@
import '../common.dart';
import '../common/names.dart';
import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
-import '../common/tasks.dart' show CompilerTask;
+import '../common/tasks.dart' show Measurer, CompilerTask;
import '../constants/constant_system.dart' as constant_system;
import '../constants/values.dart';
import '../common_elements.dart' show JCommonElements;
@@ -29,7 +29,6 @@
import '../js_emitter/code_emitter_task.dart';
import '../js_model/elements.dart' show JGeneratorBody;
import '../native/behavior.dart';
-import '../native/enqueue.dart';
import '../options.dart';
import '../tracer.dart';
import '../universe/call_structure.dart' show CallStructure;
@@ -47,12 +46,12 @@
}
class SsaCodeGeneratorTask extends CompilerTask {
- final JavaScriptBackend backend;
- final SourceInformationStrategy sourceInformationFactory;
+ final CompilerOptions _options;
+ final SourceInformationStrategy sourceInformationStrategy;
- SsaCodeGeneratorTask(JavaScriptBackend backend, this.sourceInformationFactory)
- : this.backend = backend,
- super(backend.compiler.measurer);
+ SsaCodeGeneratorTask(
+ Measurer measurer, this._options, this.sourceInformationStrategy)
+ : super(measurer);
@override
String get name => 'SSA code generator';
@@ -61,7 +60,7 @@
List<js.Parameter> parameters, js.Block body) {
js.Fun finish(js.AsyncModifier asyncModifier) {
return new js.Fun(parameters, body, asyncModifier: asyncModifier)
- .withSourceInformation(sourceInformationFactory
+ .withSourceInformation(sourceInformationStrategy
.createBuilderForContext(element)
.buildDeclaration(element));
}
@@ -79,67 +78,65 @@
}
}
- js.Expression generateCode(
- CodegenWorkItem work, HGraph graph, JClosedWorld closedWorld) {
+ js.Expression generateCode(CodegenWorkItem work, HGraph graph,
+ CodegenInputs codegen, JClosedWorld closedWorld) {
if (work.element.isField) {
- return generateLazyInitializer(work, graph, closedWorld);
+ return generateLazyInitializer(work, graph, codegen, closedWorld);
} else {
- return generateMethod(work, graph, closedWorld);
+ return generateMethod(work, graph, codegen, closedWorld);
}
}
- js.Expression generateLazyInitializer(
- CodegenWorkItem work, HGraph graph, JClosedWorld closedWorld) {
+ js.Expression generateLazyInitializer(CodegenWorkItem work, HGraph graph,
+ CodegenInputs codegen, JClosedWorld closedWorld) {
return measure(() {
- backend.tracer.traceGraph("codegen", graph);
- SourceInformation sourceInformation = sourceInformationFactory
+ codegen.tracer.traceGraph("codegen", graph);
+ SourceInformation sourceInformation = sourceInformationStrategy
.createBuilderForContext(work.element)
.buildDeclaration(work.element);
- SsaCodeGenerator codegen = new SsaCodeGenerator(
+ SsaCodeGenerator codeGenerator = new SsaCodeGenerator(
this,
- backend.compiler.options,
- backend.emitter,
- backend.nativeCodegenEnqueuer,
- backend.checkedModeHelpers,
- backend.oneShotInterceptorData,
- backend.rtiSubstitutions,
- backend.rtiEncoder,
- backend.namer,
- backend.superMemberData,
- backend.tracer,
+ _options,
+ codegen.emitter,
+ codegen.checkedModeHelpers,
+ codegen.oneShotInterceptorData,
+ codegen.rtiSubstitutions,
+ codegen.rtiEncoder,
+ codegen.namer,
+ codegen.superMemberData,
+ codegen.tracer,
closedWorld,
work);
- codegen.visitGraph(graph);
- return new js.Fun(codegen.parameters, codegen.body)
+ codeGenerator.visitGraph(graph);
+ return new js.Fun(codeGenerator.parameters, codeGenerator.body)
.withSourceInformation(sourceInformation);
});
}
- js.Expression generateMethod(
- CodegenWorkItem work, HGraph graph, JClosedWorld closedWorld) {
+ js.Expression generateMethod(CodegenWorkItem work, HGraph graph,
+ CodegenInputs codegen, JClosedWorld closedWorld) {
return measure(() {
FunctionEntity element = work.element;
if (element.asyncMarker != AsyncMarker.SYNC) {
work.registry.registerAsyncMarker(element.asyncMarker);
}
- SsaCodeGenerator codegen = new SsaCodeGenerator(
+ SsaCodeGenerator codeGenerator = new SsaCodeGenerator(
this,
- backend.compiler.options,
- backend.emitter,
- backend.nativeCodegenEnqueuer,
- backend.checkedModeHelpers,
- backend.oneShotInterceptorData,
- backend.rtiSubstitutions,
- backend.rtiEncoder,
- backend.namer,
- backend.superMemberData,
- backend.tracer,
+ _options,
+ codegen.emitter,
+ codegen.checkedModeHelpers,
+ codegen.oneShotInterceptorData,
+ codegen.rtiSubstitutions,
+ codegen.rtiEncoder,
+ codegen.namer,
+ codegen.superMemberData,
+ codegen.tracer,
closedWorld,
work);
- codegen.visitGraph(graph);
- backend.tracer.traceGraph("codegen", graph);
+ codeGenerator.visitGraph(graph);
+ codegen.tracer.traceGraph("codegen", graph);
return buildJavaScriptFunction(graph.needsAsyncRewrite, work.element,
- codegen.parameters, codegen.body);
+ codeGenerator.parameters, codeGenerator.body);
});
}
}
@@ -165,8 +162,7 @@
final CompilerTask _codegenTask;
final CompilerOptions _options;
- final CodeEmitterTask _emitter;
- final NativeCodegenEnqueuer _nativeEnqueuer;
+ final Emitter _emitter;
final CheckedModeHelpers _checkedModeHelpers;
final OneShotInterceptorData _oneShotInterceptorData;
final RuntimeTypesSubstitutions _rtiSubstitutions;
@@ -223,7 +219,6 @@
this._codegenTask,
this._options,
this._emitter,
- this._nativeEnqueuer,
this._checkedModeHelpers,
this._oneShotInterceptorData,
this._rtiSubstitutions,
@@ -2274,8 +2269,7 @@
void registerForeignTypes(HForeign node) {
NativeBehavior nativeBehavior = node.nativeBehavior;
if (nativeBehavior == null) return;
- _nativeEnqueuer.registerNativeBehavior(
- _registry.worldImpact, nativeBehavior, node);
+ _registry.registerNativeBehavior(nativeBehavior);
}
@override
@@ -3279,9 +3273,7 @@
case TypeInfoExpressionKind.COMPLETE:
int index = 0;
js.Expression result = _rtiEncoder.getTypeRepresentation(
- _emitter.emitter,
- type,
- (TypeVariableType variable) => arguments[index++]);
+ _emitter, type, (TypeVariableType variable) => arguments[index++]);
assert(
index == node.inputs.length,
"Not all input is read for type ${type}: "
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index daf93c6..88f9b6c 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -5,8 +5,7 @@
import '../common.dart';
import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
import '../common/names.dart' show Selectors;
-import '../common/tasks.dart' show CompilerTask;
-import '../compiler.dart' show Compiler;
+import '../common/tasks.dart' show Measurer, CompilerTask;
import '../constants/constant_system.dart' as constant_system;
import '../constants/values.dart';
import '../common_elements.dart' show JCommonElements;
@@ -40,28 +39,26 @@
}
class SsaOptimizerTask extends CompilerTask {
- final JavaScriptBackend _backend;
+ final CompilerOptions _options;
Map<HInstruction, Range> ranges = <HInstruction, Range>{};
Map<MemberEntity, OptimizationTestLog> loggersForTesting;
- SsaOptimizerTask(this._backend) : super(_backend.compiler.measurer);
+ SsaOptimizerTask(Measurer measurer, this._options) : super(measurer);
@override
String get name => 'SSA optimizer';
- Compiler get _compiler => _backend.compiler;
-
- CompilerOptions get _options => _compiler.options;
-
- RuntimeTypesSubstitutions get _rtiSubstitutions => _backend.rtiSubstitutions;
-
- void optimize(CodegenWorkItem work, HGraph graph, JClosedWorld closedWorld,
+ void optimize(
+ CodegenWorkItem work,
+ HGraph graph,
+ CodegenInputs codegen,
+ JClosedWorld closedWorld,
GlobalTypeInferenceResults globalInferenceResults) {
void runPhase(OptimizationPhase phase) {
measureSubtask(phase.name, () => phase.visitGraph(graph));
- _backend.tracer.traceGraph(phase.name, graph);
+ codegen.tracer.traceGraph(phase.name, graph);
assert(graph.isValid(), 'Graph not valid after ${phase.name}');
}
@@ -82,7 +79,7 @@
// Run trivial instruction simplification first to optimize
// some patterns useful for type conversion.
new SsaInstructionSimplifier(globalInferenceResults, _options,
- _rtiSubstitutions, closedWorld, registry, log),
+ codegen.rtiSubstitutions, closedWorld, registry, log),
new SsaTypeConversionInserter(closedWorld),
new SsaRedundantPhiEliminator(),
new SsaDeadPhiEliminator(),
@@ -91,10 +88,10 @@
// After type propagation, more instructions can be
// simplified.
new SsaInstructionSimplifier(globalInferenceResults, _options,
- _rtiSubstitutions, closedWorld, registry, log),
+ codegen.rtiSubstitutions, closedWorld, registry, log),
new SsaCheckInserter(trustPrimitives, closedWorld, boundsChecked),
new SsaInstructionSimplifier(globalInferenceResults, _options,
- _rtiSubstitutions, closedWorld, registry, log),
+ codegen.rtiSubstitutions, closedWorld, registry, log),
new SsaCheckInserter(trustPrimitives, closedWorld, boundsChecked),
new SsaTypePropagator(globalInferenceResults, _options,
closedWorld.commonElements, closedWorld, log),
@@ -107,7 +104,7 @@
new SsaTypePropagator(globalInferenceResults, _options,
closedWorld.commonElements, closedWorld, log),
codeMotion = new SsaCodeMotion(closedWorld.abstractValueDomain),
- loadElimination = new SsaLoadElimination(_compiler, closedWorld),
+ loadElimination = new SsaLoadElimination(closedWorld),
new SsaRedundantPhiEliminator(),
new SsaDeadPhiEliminator(),
// After GVN and load elimination the same value may be used in code
@@ -120,7 +117,7 @@
// Previous optimizations may have generated new
// opportunities for instruction simplification.
new SsaInstructionSimplifier(globalInferenceResults, _options,
- _rtiSubstitutions, closedWorld, registry, log),
+ codegen.rtiSubstitutions, closedWorld, registry, log),
new SsaCheckInserter(trustPrimitives, closedWorld, boundsChecked),
];
phases.forEach(runPhase);
@@ -143,7 +140,7 @@
new SsaCodeMotion(closedWorld.abstractValueDomain),
new SsaValueRangeAnalyzer(closedWorld, this),
new SsaInstructionSimplifier(globalInferenceResults, _options,
- _rtiSubstitutions, closedWorld, registry, log),
+ codegen.rtiSubstitutions, closedWorld, registry, log),
new SsaCheckInserter(trustPrimitives, closedWorld, boundsChecked),
new SsaSimplifyInterceptors(closedWorld, work.element.enclosingClass),
new SsaDeadCodeEliminator(closedWorld, this),
@@ -155,7 +152,7 @@
// Run the simplifier to remove unneeded type checks inserted by
// type propagation.
new SsaInstructionSimplifier(globalInferenceResults, _options,
- _rtiSubstitutions, closedWorld, registry, log),
+ codegen.rtiSubstitutions, closedWorld, registry, log),
];
}
phases.forEach(runPhase);
@@ -2946,7 +2943,6 @@
/// [HFieldGet]), when it knows the value stored in that memory location, and
/// stores that overwrite with the same value.
class SsaLoadElimination extends HBaseVisitor implements OptimizationPhase {
- final Compiler compiler;
final JClosedWorld _closedWorld;
final JFieldAnalysis _fieldAnalysis;
@override
@@ -2956,7 +2952,7 @@
bool newGvnCandidates = false;
HGraph _graph;
- SsaLoadElimination(this.compiler, this._closedWorld)
+ SsaLoadElimination(this._closedWorld)
: _fieldAnalysis = _closedWorld.fieldAnalysis;
AbstractValueDomain get _abstractValueDomain =>
diff --git a/pkg/compiler/lib/src/ssa/ssa.dart b/pkg/compiler/lib/src/ssa/ssa.dart
index ed857e1..c6e963e 100644
--- a/pkg/compiler/lib/src/ssa/ssa.dart
+++ b/pkg/compiler/lib/src/ssa/ssa.dart
@@ -4,13 +4,22 @@
library ssa;
-import '../common/codegen.dart' show CodegenWorkItem;
+import '../backend_strategy.dart';
+import '../common.dart';
+import '../common_elements.dart' show CommonElements, JElementEnvironment;
+import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
import '../common/tasks.dart' show CompilerTask, Measurer;
-import '../elements/entities.dart' show MemberEntity;
+import '../elements/entities.dart';
+import '../elements/types.dart';
import '../inferrer/types.dart';
import '../io/source_information.dart';
import '../js/js.dart' as js;
-import '../js_backend/backend.dart' show JavaScriptBackend, FunctionCompiler;
+import '../js/rewrite_async.dart';
+import '../js_backend/backend.dart' show CodegenInputs, FunctionCompiler;
+import '../js_model/elements.dart';
+import '../options.dart';
+import '../universe/call_structure.dart' show CallStructure;
+import '../universe/use.dart' show StaticUse;
import '../world.dart' show JClosedWorld;
import 'codegen.dart';
@@ -18,37 +27,49 @@
import 'optimize.dart';
class SsaFunctionCompiler implements FunctionCompiler {
+ final DiagnosticReporter _reporter;
final SsaCodeGeneratorTask generator;
final SsaBuilderTask _builder;
final SsaOptimizerTask optimizer;
- final JavaScriptBackend backend;
+ final SourceInformationStrategy sourceInformationStrategy;
- SsaFunctionCompiler(JavaScriptBackend backend, Measurer measurer,
- SourceInformationStrategy sourceInformationFactory)
- : generator = new SsaCodeGeneratorTask(backend, sourceInformationFactory),
- _builder = new SsaBuilderTask(backend, sourceInformationFactory),
- optimizer = new SsaOptimizerTask(backend),
- backend = backend;
+ SsaFunctionCompiler(
+ CompilerOptions options,
+ this._reporter,
+ BackendStrategy backendStrategy,
+ Measurer measurer,
+ this.sourceInformationStrategy)
+ : generator = new SsaCodeGeneratorTask(
+ measurer, options, sourceInformationStrategy),
+ _builder = new SsaBuilderTask(
+ measurer, backendStrategy, sourceInformationStrategy),
+ optimizer = new SsaOptimizerTask(measurer, options);
@override
- void onCodegenStart() {
- _builder.onCodegenStart();
+ void onCodegenStart(CodegenInputs codegen) {
+ _builder.onCodegenStart(codegen);
}
/// Generates JavaScript code for `work.element`.
/// Using the ssa builder, optimizer and code generator.
@override
- js.Fun compile(CodegenWorkItem work, JClosedWorld closedWorld,
+ js.Fun compile(
+ CodegenWorkItem work,
+ CodegenInputs codegen,
+ JClosedWorld closedWorld,
GlobalTypeInferenceResults globalInferenceResults) {
HGraph graph = _builder.build(work, closedWorld, globalInferenceResults);
if (graph == null) return null;
- optimizer.optimize(work, graph, closedWorld, globalInferenceResults);
+ optimizer.optimize(
+ work, graph, codegen, closedWorld, globalInferenceResults);
MemberEntity element = work.element;
- js.Expression result = generator.generateCode(work, graph, closedWorld);
+ js.Expression result =
+ generator.generateCode(work, graph, codegen, closedWorld);
if (graph.needsAsyncRewrite) {
SourceInformationBuilder sourceInformationBuilder =
- backend.sourceInformationStrategy.createBuilderForContext(element);
- result = backend.rewriteAsync(
+ sourceInformationStrategy.createBuilderForContext(element);
+ result = _rewriteAsync(
+ codegen,
closedWorld.commonElements,
closedWorld.elementEnvironment,
work.registry,
@@ -61,6 +82,132 @@
return result;
}
+ js.Expression _rewriteAsync(
+ CodegenInputs codegen,
+ CommonElements commonElements,
+ JElementEnvironment elementEnvironment,
+ CodegenRegistry registry,
+ FunctionEntity element,
+ js.Expression code,
+ DartType asyncTypeParameter,
+ SourceInformation bodySourceInformation,
+ SourceInformation exitSourceInformation) {
+ if (element.asyncMarker == AsyncMarker.SYNC) return code;
+
+ AsyncRewriterBase rewriter = null;
+ js.Name name = codegen.namer.methodPropertyName(
+ element is JGeneratorBody ? element.function : element);
+
+ switch (element.asyncMarker) {
+ case AsyncMarker.ASYNC:
+ rewriter = _makeAsyncRewriter(
+ codegen,
+ commonElements,
+ elementEnvironment,
+ registry,
+ element,
+ code,
+ asyncTypeParameter,
+ name);
+ break;
+ case AsyncMarker.SYNC_STAR:
+ rewriter = new SyncStarRewriter(_reporter, element,
+ endOfIteration: codegen.emitter
+ .staticFunctionAccess(commonElements.endOfIteration),
+ iterableFactory: codegen.emitter
+ .staticFunctionAccess(commonElements.syncStarIterableFactory),
+ iterableFactoryTypeArguments:
+ _fetchItemType(codegen, asyncTypeParameter),
+ yieldStarExpression:
+ codegen.emitter.staticFunctionAccess(commonElements.yieldStar),
+ uncaughtErrorExpression: codegen.emitter
+ .staticFunctionAccess(commonElements.syncStarUncaughtError),
+ safeVariableName: codegen.namer.safeVariablePrefixForAsyncRewrite,
+ bodyName: codegen.namer.deriveAsyncBodyName(name));
+ registry.registerStaticUse(new StaticUse.staticInvoke(
+ commonElements.syncStarIterableFactory,
+ const CallStructure.unnamed(1, 1), [
+ elementEnvironment.getFunctionAsyncOrSyncStarElementType(element)
+ ]));
+ break;
+ case AsyncMarker.ASYNC_STAR:
+ rewriter = new AsyncStarRewriter(_reporter, element,
+ asyncStarHelper: codegen.emitter
+ .staticFunctionAccess(commonElements.asyncStarHelper),
+ streamOfController: codegen.emitter
+ .staticFunctionAccess(commonElements.streamOfController),
+ wrapBody:
+ codegen.emitter.staticFunctionAccess(commonElements.wrapBody),
+ newController: codegen.emitter.staticFunctionAccess(
+ commonElements.asyncStarStreamControllerFactory),
+ newControllerTypeArguments:
+ _fetchItemType(codegen, asyncTypeParameter),
+ safeVariableName: codegen.namer.safeVariablePrefixForAsyncRewrite,
+ yieldExpression: codegen.emitter
+ .staticFunctionAccess(commonElements.yieldSingle),
+ yieldStarExpression:
+ codegen.emitter.staticFunctionAccess(commonElements.yieldStar),
+ bodyName: codegen.namer.deriveAsyncBodyName(name));
+ registry.registerStaticUse(new StaticUse.staticInvoke(
+ commonElements.asyncStarStreamControllerFactory,
+ const CallStructure.unnamed(1, 1), [
+ elementEnvironment.getFunctionAsyncOrSyncStarElementType(element)
+ ]));
+ break;
+ }
+ return rewriter.rewrite(code, bodySourceInformation, exitSourceInformation);
+ }
+
+ /// Returns an optional expression that evaluates [type]. Returns `null` if
+ /// the type expression is determined by the outside context and should be
+ /// added as a function parameter to the rewritten code.
+ // TODO(sra): We could also return an empty list if the generator takes no
+ // type (e.g. due to rtiNeed optimization).
+ List<js.Expression> _fetchItemType(CodegenInputs codegen, DartType type) {
+ if (type == null) return null;
+ var ast =
+ codegen.rtiEncoder.getTypeRepresentation(codegen.emitter, type, null);
+ return <js.Expression>[ast];
+ }
+
+ AsyncRewriter _makeAsyncRewriter(
+ CodegenInputs codegen,
+ CommonElements commonElements,
+ JElementEnvironment elementEnvironment,
+ CodegenRegistry registry,
+ FunctionEntity element,
+ js.Expression code,
+ DartType elementType,
+ js.Name name) {
+ FunctionEntity startFunction = commonElements.asyncHelperStartSync;
+ FunctionEntity completerFactory = commonElements.asyncAwaitCompleterFactory;
+
+ List<js.Expression> itemTypeExpression =
+ _fetchItemType(codegen, elementType);
+
+ AsyncRewriter rewriter = new AsyncRewriter(_reporter, element,
+ asyncStart: codegen.emitter.staticFunctionAccess(startFunction),
+ asyncAwait: codegen.emitter
+ .staticFunctionAccess(commonElements.asyncHelperAwait),
+ asyncReturn: codegen.emitter
+ .staticFunctionAccess(commonElements.asyncHelperReturn),
+ asyncRethrow: codegen.emitter
+ .staticFunctionAccess(commonElements.asyncHelperRethrow),
+ wrapBody: codegen.emitter.staticFunctionAccess(commonElements.wrapBody),
+ completerFactory:
+ codegen.emitter.staticFunctionAccess(completerFactory),
+ completerFactoryTypeArguments: itemTypeExpression,
+ safeVariableName: codegen.namer.safeVariablePrefixForAsyncRewrite,
+ bodyName: codegen.namer.deriveAsyncBodyName(name));
+
+ registry.registerStaticUse(new StaticUse.staticInvoke(
+ completerFactory,
+ const CallStructure.unnamed(0, 1),
+ [elementEnvironment.getFunctionAsyncOrSyncStarElementType(element)]));
+
+ return rewriter;
+ }
+
@override
Iterable<CompilerTask> get tasks {
return <CompilerTask>[_builder, optimizer, generator];
@@ -75,19 +222,20 @@
}
class SsaBuilderTask extends CompilerTask {
- final JavaScriptBackend _backend;
+ final BackendStrategy _backendStrategy;
final SourceInformationStrategy _sourceInformationFactory;
SsaBuilder _builder;
- SsaBuilderTask(this._backend, this._sourceInformationFactory)
- : super(_backend.compiler.measurer);
+ SsaBuilderTask(
+ Measurer measurer, this._backendStrategy, this._sourceInformationFactory)
+ : super(measurer);
@override
String get name => 'SSA builder';
- void onCodegenStart() {
- _builder = _backend.compiler.backendStrategy
- .createSsaBuilder(this, _backend, _sourceInformationFactory);
+ void onCodegenStart(CodegenInputs codegen) {
+ _builder = _backendStrategy.createSsaBuilder(
+ this, codegen, _sourceInformationFactory);
}
/// Creates the [HGraph] for [work] or returns `null` if no code is needed
diff --git a/tests/compiler/dart2js/codegen/is_function_test.dart b/tests/compiler/dart2js/codegen/is_function_test.dart
index 53cbaf3..e0b3aea 100644
--- a/tests/compiler/dart2js/codegen/is_function_test.dart
+++ b/tests/compiler/dart2js/codegen/is_function_test.dart
@@ -24,7 +24,7 @@
memorySourceFiles: {'main.dart': SOURCE}, options: options);
Expect.isTrue(result.isSuccess);
Compiler compiler = result.compiler;
- Program program = compiler.backend.emitter.emitter.programForTesting;
+ Program program = compiler.backend.emitterTask.emitter.programForTesting;
var name = compiler.backend.namer.operatorIs(
compiler.backendClosedWorldForTesting.commonElements.functionClass);
for (Fragment fragment in program.fragments) {
diff --git a/tests/compiler/dart2js/deferred/load_graph_segmentation_test.dart b/tests/compiler/dart2js/deferred/load_graph_segmentation_test.dart
index e79c1f8..45bd24b 100644
--- a/tests/compiler/dart2js/deferred/load_graph_segmentation_test.dart
+++ b/tests/compiler/dart2js/deferred/load_graph_segmentation_test.dart
@@ -29,7 +29,7 @@
var mainOutputUnit = closedWorld.outputUnitData.mainOutputUnit;
var backend = compiler.backend;
- var classes = backend.emitter.neededClasses;
+ var classes = backend.emitterTask.neededClasses;
var inputElement = classes.where((e) => e.name == 'InputElement').single;
dynamic lib1 = lookupLibrary("memory:lib1.dart");
var foo1 = env.lookupLibraryMember(lib1, "foo1");
diff --git a/tests/compiler/dart2js/helpers/program_lookup.dart b/tests/compiler/dart2js/helpers/program_lookup.dart
index f4ce6d9e..6aff382 100644
--- a/tests/compiler/dart2js/helpers/program_lookup.dart
+++ b/tests/compiler/dart2js/helpers/program_lookup.dart
@@ -43,7 +43,7 @@
final Namer namer;
ProgramLookup(Compiler compiler)
- : this.program = compiler.backend.emitter.emitter.programForTesting,
+ : this.program = compiler.backend.emitterTask.emitter.programForTesting,
this.namer = compiler.backend.namer;
Fragment getFragment(OutputUnit outputUnit) {
diff --git a/tests/compiler/dart2js/rti/type_representation_test.dart b/tests/compiler/dart2js/rti/type_representation_test.dart
index 6e7eaef..97bd3d6 100644
--- a/tests/compiler/dart2js/rti/type_representation_test.dart
+++ b/tests/compiler/dart2js/rti/type_representation_test.dart
@@ -85,12 +85,18 @@
[String expectedTypedefRepresentation]) {
bool encodeTypedefName = false;
Expression expression = typeRepresentation.getTypeRepresentation(
- backend.emitter.emitter, type, onVariable, (x) => encodeTypedefName);
+ backend.emitterTask.emitter,
+ type,
+ onVariable,
+ (x) => encodeTypedefName);
Expect.stringEquals(expectedRepresentation, stringify(expression));
encodeTypedefName = true;
expression = typeRepresentation.getTypeRepresentation(
- backend.emitter.emitter, type, onVariable, (x) => encodeTypedefName);
+ backend.emitterTask.emitter,
+ type,
+ onVariable,
+ (x) => encodeTypedefName);
if (expectedTypedefRepresentation == null) {
expectedTypedefRepresentation = expectedRepresentation;
}
@@ -98,8 +104,8 @@
}
String getJsName(Entity cls) {
- Expression name =
- typeRepresentation.getJavaScriptClassName(cls, backend.emitter.emitter);
+ Expression name = typeRepresentation.getJavaScriptClassName(
+ cls, backend.emitterTask.emitter);
return stringify(name);
}