Extract ModularEmitterImpl superclass from EmitterImpl
Change-Id: I7e7a87743d24e5da6401937b3983a358062a2296
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/101523
Reviewed-by: Sigmund Cherem <sigmund@google.com>
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index 49cc060..f28aa79 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -935,27 +935,15 @@
: _disambiguateGlobalMember(element);
}
- /// Returns a JavaScript property name used to store the member [element] on
- /// one of the global objects.
- ///
- /// Should be used together with [globalObjectForMember], which denotes the
- /// object on which the returned property name should be used.
+ @override
jsAst.Name globalPropertyNameForMember(MemberEntity element) =>
_disambiguateGlobalMember(element);
- /// Returns a JavaScript property name used to store the class [element] on
- /// one of the global objects.
- ///
- /// Should be used together with [globalObjectForClass], which denotes the
- /// object on which the returned property name should be used.
+ @override
jsAst.Name globalPropertyNameForClass(ClassEntity element) =>
_disambiguateGlobalType(element);
- /// Returns a JavaScript property name used to store the type (typedef)
- /// [element] on one of the global objects.
- ///
- /// Should be used together with [globalObjectForType], which denotes the
- /// object on which the returned property name should be used.
+ @override
jsAst.Name globalPropertyNameForType(Entity element) =>
_disambiguateGlobalType(element);
@@ -1553,10 +1541,23 @@
return globalObjectForLibrary(element.library);
}
+ @override
+ jsAst.VariableUse readGlobalObjectForMember(MemberEntity element) {
+ if (_isPropertyOfStaticStateHolder(element)) {
+ return new jsAst.VariableUse(staticStateHolder);
+ }
+ return readGlobalObjectForLibrary(element.library);
+ }
+
String globalObjectForClass(ClassEntity element) {
return globalObjectForLibrary(element.library);
}
+ @override
+ jsAst.VariableUse readGlobalObjectForClass(ClassEntity element) {
+ return readGlobalObjectForLibrary(element.library);
+ }
+
String globalObjectForType(Entity element) {
if (element is TypedefEntity) {
return globalObjectForLibrary(element.library);
@@ -1564,6 +1565,14 @@
return globalObjectForClass(element);
}
+ @override
+ jsAst.VariableUse readGlobalObjectForType(Entity element) {
+ if (element is TypedefEntity) {
+ return readGlobalObjectForLibrary(element.library);
+ }
+ return readGlobalObjectForClass(element);
+ }
+
/// Returns the [reservedGlobalObjectNames] for [library].
String globalObjectForLibrary(LibraryEntity library) {
if (library == _commonElements.interceptorsLibrary) return 'J';
@@ -1581,6 +1590,7 @@
return new jsAst.VariableUse(globalObjectForLibrary(library));
}
+ @override
jsAst.Name lazyInitializerName(FieldEntity element) {
assert(element.isTopLevel || element.isStatic);
jsAst.Name name = _disambiguateGlobal<MemberEntity>(
@@ -1588,6 +1598,7 @@
return name;
}
+ @override
jsAst.Name staticClosureName(FunctionEntity element) {
assert(element.isTopLevel || element.isStatic);
String enclosing =
@@ -2335,9 +2346,48 @@
/// Namer interface that can be used in modular code generation.
abstract class ModularNamer {
- /// Returns a variable use of the [reservedGlobalObjectNames] for [library].
+ /// Returns a variable use for accessing [library].
+ ///
+ /// This is one of the [reservedGlobalObjectNames]
jsAst.VariableUse readGlobalObjectForLibrary(LibraryEntity library);
+ /// Returns a variable use for accessing the class [element].
+ ///
+ /// This is one of the [reservedGlobalObjectNames]
+ jsAst.VariableUse readGlobalObjectForClass(ClassEntity element);
+
+ /// Returns a variable use for accessing the type [element].
+ ///
+ /// This is one of the [reservedGlobalObjectNames]
+ jsAst.VariableUse readGlobalObjectForType(Entity element);
+
+ /// Returns a variable use for accessing the member [element].
+ ///
+ /// This is either the [staticStateHolder] or one of the
+ /// [reservedGlobalObjectNames]
+ jsAst.VariableUse readGlobalObjectForMember(MemberEntity element);
+
+ /// Returns a JavaScript property name used to store the class [element] on
+ /// one of the global objects.
+ ///
+ /// Should be used together with [globalObjectForClass], which denotes the
+ /// object on which the returned property name should be used.
+ jsAst.Name globalPropertyNameForClass(ClassEntity element);
+
+ /// Returns a JavaScript property name used to store the member [element] on
+ /// one of the global objects.
+ ///
+ /// Should be used together with [globalObjectForMember], which denotes the
+ /// object on which the returned property name should be used.
+ jsAst.Name globalPropertyNameForMember(MemberEntity element);
+
+ /// Returns a JavaScript property name used to store the type (typedef)
+ /// [element] on one of the global objects.
+ ///
+ /// Should be used together with [globalObjectForType], which denotes the
+ /// object on which the returned property name should be used.
+ jsAst.Name globalPropertyNameForType(Entity element);
+
/// Returns the name for the instance field that holds runtime type arguments
/// on generic classes.
jsAst.Name get rtiFieldJsName;
@@ -2387,8 +2437,6 @@
/// collisions.
jsAst.Name nameForGetInterceptor(Iterable<ClassEntity> classes);
- jsAst.Name operatorIsType(DartType type);
-
/// Returns the runtime name for [element].
///
/// This name is used as the basis for deriving `is` and `as` property names
@@ -2429,10 +2477,19 @@
/// [element].
jsAst.Name operatorIs(ClassEntity element);
+ /// Return the name of the `isX` property for classes that implement [type].
+ jsAst.Name operatorIsType(DartType type);
+
/// Returns the name of the `asX` function for classes that implement the
/// generic class [element].
jsAst.Name substitutionName(ClassEntity element);
+ /// Returns the name of the lazy initializer for the static field [element].
+ jsAst.Name lazyInitializerName(FieldEntity element);
+
+ /// Returns the name of the closure of the static method [element].
+ jsAst.Name staticClosureName(FunctionEntity element);
+
/// Returns the label name for [label] used as a break target.
String breakLabelName(LabelDefinition label) {
return '\$${label.labelName}\$${label.target.nestingLevel}';
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 b04b3cb..99a79d1 100644
--- a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
+++ b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
@@ -168,7 +168,7 @@
jsAst.Expression isolateLazyInitializerAccess(covariant FieldEntity element);
/// Returns the closure expression of a static function.
- jsAst.Expression isolateStaticClosureAccess(covariant FunctionEntity element);
+ jsAst.Expression staticClosureAccess(covariant FunctionEntity element);
/// Returns the JS constructor of the given element.
///
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 c82d0aa..a2095b5 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
@@ -16,21 +16,98 @@
import '../../elements/entities.dart';
import '../../io/source_information.dart';
import '../../js/js.dart' as js;
-import '../../js_backend/js_backend.dart' show Namer;
+import '../../js_backend/js_backend.dart' show ModularNamer, Namer;
import '../../js_backend/runtime_types.dart';
import '../../options.dart';
import '../../universe/codegen_world_builder.dart' show CodegenWorld;
import '../../world.dart' show JClosedWorld;
-import '../js_emitter.dart' show Emitter;
+import '../js_emitter.dart' show Emitter, ModularEmitter;
import '../model.dart';
import '../program_builder/program_builder.dart' show ProgramBuilder;
import 'model_emitter.dart';
-class EmitterImpl implements Emitter {
+class ModularEmitterImpl implements ModularEmitter {
+ final ModularNamer _namer;
+
+ ModularEmitterImpl(this._namer);
+
+ js.PropertyAccess globalPropertyAccessForClass(ClassEntity element) {
+ js.Name name = _namer.globalPropertyNameForClass(element);
+ js.PropertyAccess pa =
+ new js.PropertyAccess(_namer.readGlobalObjectForClass(element), name);
+ return pa;
+ }
+
+ js.PropertyAccess globalPropertyAccessForType(Entity element) {
+ js.Name name = _namer.globalPropertyNameForType(element);
+ js.PropertyAccess pa =
+ new js.PropertyAccess(_namer.readGlobalObjectForType(element), name);
+ return pa;
+ }
+
+ js.PropertyAccess globalPropertyAccessForMember(MemberEntity element) {
+ js.Name name = _namer.globalPropertyNameForMember(element);
+ js.PropertyAccess pa =
+ new js.PropertyAccess(_namer.readGlobalObjectForMember(element), name);
+ return pa;
+ }
+
+ @override
+ js.PropertyAccess constructorAccess(ClassEntity element) {
+ return globalPropertyAccessForClass(element);
+ }
+
+ @override
+ js.Expression isolateLazyInitializerAccess(FieldEntity element) {
+ return new js.PropertyAccess(_namer.readGlobalObjectForMember(element),
+ _namer.lazyInitializerName(element));
+ }
+
+ @override
+ js.PropertyAccess staticFunctionAccess(FunctionEntity element) {
+ return globalPropertyAccessForMember(element);
+ }
+
+ @override
+ js.PropertyAccess staticFieldAccess(FieldEntity element) {
+ return globalPropertyAccessForMember(element);
+ }
+
+ @override
+ js.PropertyAccess prototypeAccess(ClassEntity element,
+ {bool hasBeenInstantiated}) {
+ js.Expression constructor =
+ hasBeenInstantiated ? constructorAccess(element) : typeAccess(element);
+ return js.js('#.prototype', constructor);
+ }
+
+ js.Expression typeAccess(Entity element) {
+ return globalPropertyAccessForType(element);
+ }
+
+ @override
+ js.Expression staticClosureAccess(FunctionEntity element) {
+ return new js.Call(
+ new js.PropertyAccess(_namer.readGlobalObjectForMember(element),
+ _namer.staticClosureName(element)),
+ const []);
+ }
+
+ @override
+ js.Expression constantReference(ConstantValue constant) {
+ throw new UnimplementedError("ModularEmitter.constantReference");
+ }
+
+ @override
+ js.Expression generateEmbeddedGlobalAccess(String global) {
+ throw new UnimplementedError("ModularEmitter.generateEmbeddedGlobalAccess");
+ }
+}
+
+class EmitterImpl extends ModularEmitterImpl implements Emitter {
final DiagnosticReporter _reporter;
final JClosedWorld _closedWorld;
final RuntimeTypesEncoder _rtiEncoder;
- final Namer namer;
ModelEmitter _emitter;
@override
@@ -41,12 +118,13 @@
this._reporter,
CompilerOutput outputProvider,
DumpInfoTask dumpInfoTask,
- this.namer,
+ Namer namer,
this._closedWorld,
this._rtiEncoder,
SourceInformationStrategy sourceInformationStrategy,
CompilerTask task,
- bool shouldGenerateSourceMap) {
+ bool shouldGenerateSourceMap)
+ : super(namer) {
_emitter = new ModelEmitter(
options,
_reporter,
@@ -62,6 +140,9 @@
}
@override
+ Namer get _namer => super._namer;
+
+ @override
int emitProgram(ProgramBuilder programBuilder, CodegenWorld codegenWorld) {
Program program = programBuilder.buildProgram();
if (retainDataForTesting) {
@@ -70,53 +151,12 @@
return _emitter.emitProgram(program, codegenWorld);
}
- js.PropertyAccess globalPropertyAccessForMember(MemberEntity element) {
- js.Name name = namer.globalPropertyNameForMember(element);
- js.PropertyAccess pa = new js.PropertyAccess(
- new js.VariableUse(namer.globalObjectForMember(element)), name);
- return pa;
- }
-
- js.PropertyAccess globalPropertyAccessForClass(ClassEntity element) {
- js.Name name = namer.globalPropertyNameForClass(element);
- js.PropertyAccess pa = new js.PropertyAccess(
- new js.VariableUse(namer.globalObjectForClass(element)), name);
- return pa;
- }
-
- js.PropertyAccess globalPropertyAccessForType(Entity element) {
- js.Name name = namer.globalPropertyNameForType(element);
- js.PropertyAccess pa = new js.PropertyAccess(
- new js.VariableUse(namer.globalObjectForType(element)), name);
- return pa;
- }
-
- @override
- js.PropertyAccess staticFieldAccess(FieldEntity element) {
- return globalPropertyAccessForMember(element);
- }
-
- @override
- js.PropertyAccess staticFunctionAccess(FunctionEntity element) {
- return globalPropertyAccessForMember(element);
- }
-
- @override
- js.PropertyAccess constructorAccess(ClassEntity element) {
- return globalPropertyAccessForClass(element);
- }
-
@override
js.Expression interceptorClassAccess(ClassEntity element) {
return globalPropertyAccessForClass(element);
}
@override
- js.Expression typeAccess(Entity element) {
- return globalPropertyAccessForType(element);
- }
-
- @override
bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant) {
return _emitter.isConstantInlinedOrAlreadyEmitted(constant);
}
@@ -143,27 +183,6 @@
}
@override
- js.Expression isolateLazyInitializerAccess(FieldEntity element) {
- return js.js('#.#', [
- namer.globalObjectForMember(element),
- namer.lazyInitializerName(element)
- ]);
- }
-
- @override
- js.Expression isolateStaticClosureAccess(FunctionEntity element) {
- return _emitter.generateStaticClosureAccess(element);
- }
-
- @override
- 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));
}
@@ -176,7 +195,7 @@
return js.js.expressionTemplateYielding(typeAccess(objectClass));
case JsBuiltin.isCheckPropertyToJsConstructorName:
- int isPrefixLength = namer.operatorIsPrefix.length;
+ int isPrefixLength = _namer.operatorIsPrefix.length;
return js.js.expressionTemplateFor('#.substring($isPrefixLength)');
case JsBuiltin.isFunctionType:
@@ -203,7 +222,7 @@
case JsBuiltin.isSubtype:
// TODO(floitsch): move this closer to where is-check properties are
// built.
- String isPrefix = namer.operatorIsPrefix;
+ String isPrefix = _namer.operatorIsPrefix;
return js.js.expressionTemplateFor("('$isPrefix' + #) in #.prototype");
case JsBuiltin.isGivenTypeRti:
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
index 8dcae67..5d3f455 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
@@ -155,17 +155,10 @@
return _constantOrdering.compare(a, b);
}
- js.Expression generateStaticClosureAccess(FunctionEntity element) {
- return js.js('#.#()', [
- _namer.globalObjectForMember(element),
- _namer.staticClosureName(element)
- ]);
- }
-
js.Expression generateConstantReference(ConstantValue value) {
if (value.isFunction) {
FunctionConstantValue functionConstant = value;
- return generateStaticClosureAccess(functionConstant.element);
+ return _emitter.staticClosureAccess(functionConstant.element);
}
// We are only interested in the "isInlined" part, but it does not hurt to
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index 3072911..80e28c7 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -2641,7 +2641,7 @@
assert(element.isFunction || element.isField);
if (element.isFunction) {
push(_emitter
- .isolateStaticClosureAccess(element)
+ .staticClosureAccess(element)
.withSourceInformation(node.sourceInformation));
_registry.registerStaticUse(new StaticUse.staticTearOff(element));
} else {