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

Unified Diff: lib/src/compiler/code_generator.dart

Issue 1958193002: optimize self-references in generic type definitions (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | test/codegen/language/generic_self_reference_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/src/compiler/code_generator.dart
diff --git a/lib/src/compiler/code_generator.dart b/lib/src/compiler/code_generator.dart
index f758d14bbcabe38bcf874d80a1988036442dae46..cd63211b8dd6f0a6f2636253bd20684368b14d6b 100644
--- a/lib/src/compiler/code_generator.dart
+++ b/lib/src/compiler/code_generator.dart
@@ -458,7 +458,7 @@ class CodeGenerator extends GeneralizingAstVisitor
return fromExpr;
}
- return js.call('dart.as(#, #)', [fromExpr, _emitTypeName(to)]);
+ return js.call('dart.as(#, #)', [fromExpr, _emitType(to)]);
}
@override
@@ -472,7 +472,7 @@ class CodeGenerator extends GeneralizingAstVisitor
result = js.call('typeof # == #', [lhs, js.string(typeofName, "'")]);
} else {
// Always go through a runtime helper, because implicit interfaces.
- result = js.call('dart.is(#, #)', [lhs, _emitTypeName(type)]);
+ result = js.call('dart.is(#, #)', [lhs, _emitType(type)]);
}
if (node.notOperator != null) {
@@ -495,7 +495,7 @@ class CodeGenerator extends GeneralizingAstVisitor
JS.Expression body = annotate(
js.call('dart.typedef(#, () => #)', [
js.string(element.name, "'"),
- _emitTypeName(element.type, lowerTypedef: true)
+ _emitType(element.type, lowerTypedef: true)
]),
node,
element);
@@ -513,7 +513,7 @@ class CodeGenerator extends GeneralizingAstVisitor
JS.Expression visitTypeName(TypeName node) {
// TODO(jmesserly): should only happen for erroneous code.
if (node.type == null) return js.call('dart.dynamic');
- return _emitTypeName(node.type);
+ return _emitType(node.type);
}
@override
@@ -741,7 +741,7 @@ class CodeGenerator extends GeneralizingAstVisitor
var values = new JS.ArrayInitializer(new List<JS.Expression>.from(
fields.map((f) => js.call('#.#', [id, f.name]))));
result.add(js.statement('#.values = dart.const(dart.list(#, #));',
- [id, values, _emitTypeName(type)]));
+ [id, values, _emitType(type)]));
return _statement(result);
}
@@ -759,7 +759,7 @@ class CodeGenerator extends GeneralizingAstVisitor
]);
var dynType = fillDynamicTypeArgs(element.type);
- var genericInst = _emitTypeName(dynType, lowerGeneric: true);
+ var genericInst = _emitType(dynType, lowerGeneric: true);
return js.statement(
'{ #; # = #; }', [genericDef, _emitTopLevelName(element), genericInst]);
}
@@ -804,10 +804,10 @@ class CodeGenerator extends GeneralizingAstVisitor
supertype = fillDynamicTypeArgs(supertype.element.type);
_hasDeferredSupertype.add(element);
}
- heritage = _emitTypeName(supertype);
+ heritage = _emitType(supertype);
if (type.mixins.isNotEmpty) {
- var mixins = type.mixins.map(_emitTypeName).toList();
+ var mixins = type.mixins.map(_emitType).toList();
mixins.insert(0, heritage);
heritage = js.call('dart.mixin(#)', [mixins]);
}
@@ -1051,7 +1051,8 @@ class CodeGenerator extends GeneralizingAstVisitor
// TODO(jmesserly): we should really just extend Array in the first place.
newBaseClass = js.call('dart.global.#', [jsPeerName]);
} else if (_hasDeferredSupertype.contains(classElem)) {
- newBaseClass = _emitTypeName(classElem.type.superclass);
+ newBaseClass = _emitType(classElem.type.superclass,
+ subClass: classElem, className: className);
}
if (newBaseClass != null) {
body.add(
@@ -1136,7 +1137,7 @@ class CodeGenerator extends GeneralizingAstVisitor
body.add(js.statement('#[dart.implements] = () => #;', [
className,
new JS.ArrayInitializer(new List<JS.Expression>.from(
- classElem.interfaces.map(_emitTypeName)))
+ classElem.interfaces.map(_emitType)))
]));
}
@@ -1608,7 +1609,7 @@ class CodeGenerator extends GeneralizingAstVisitor
var paramType = param.element.type;
if (!constructor && _hasUnsoundTypeParameter(paramType)) {
body.add(js
- .statement('dart.as(#, #);', [jsParam, _emitTypeName(paramType)]));
+ .statement('dart.as(#, #);', [jsParam, _emitType(paramType)]));
}
}
return body.isEmpty ? null : _statement(body);
@@ -1989,7 +1990,7 @@ class CodeGenerator extends GeneralizingAstVisitor
gen = js.call('#.bind(this)', gen);
}
- var T = _emitTypeName(returnType);
+ var T = _emitType(returnType);
return js.call('dart.#(#)', [
kind,
[gen, T]..addAll(visitFormalParameterList(parameters, destructure: false))
@@ -2052,7 +2053,7 @@ class CodeGenerator extends GeneralizingAstVisitor
// type literal
if (element is TypeDefiningElement) {
- var typeName = _emitTypeName(fillDynamicTypeArgs(element.type));
+ var typeName = _emitType(fillDynamicTypeArgs(element.type));
// If the type is a type literal expression in Dart code, wrap the raw
// runtime type in a "Type" instance.
@@ -2081,7 +2082,7 @@ class CodeGenerator extends GeneralizingAstVisitor
// library prefix. We don't need those because static calls can't use
// the generic type.
if (isStatic) {
- var dynType = _emitTypeName(fillDynamicTypeArgs(type));
+ var dynType = _emitType(fillDynamicTypeArgs(type));
return new JS.PropertyAccess(dynType, member);
}
@@ -2157,7 +2158,7 @@ class CodeGenerator extends GeneralizingAstVisitor
for (int i = 0; i < types.length; ++i) {
var metadata =
parameters != null ? _parameterMetadata(parameters[i]) : [];
- var typeName = _emitTypeName(types[i]);
+ var typeName = _emitType(types[i]);
var value = typeName;
// TODO(vsm): Make this optional per #268.
if (metadata.isNotEmpty) {
@@ -2173,7 +2174,7 @@ class CodeGenerator extends GeneralizingAstVisitor
var properties = <JS.Property>[];
types.forEach((name, type) {
var key = _propertyName(name);
- var value = _emitTypeName(type);
+ var value = _emitType(type);
properties.add(new JS.Property(key, value));
});
return new JS.ObjectInitializer(properties);
@@ -2186,7 +2187,7 @@ class CodeGenerator extends GeneralizingAstVisitor
var parameterTypes = type.normalParameterTypes;
var optionalTypes = type.optionalParameterTypes;
var namedTypes = type.namedParameterTypes;
- var rt = _emitTypeName(type.returnType);
+ var rt = _emitType(type.returnType);
var ra = _emitTypeNames(parameterTypes, parameters);
List<JS.Expression> typeParts;
@@ -2221,8 +2222,15 @@ class CodeGenerator extends GeneralizingAstVisitor
/// function type. Similarly if [lowerGeneric] is set, the `List$()` form
/// will be used instead of `List`. These flags are used when generating
/// the definitions for typedefs and generic types, respectively.
- JS.Expression _emitTypeName(DartType type,
- {bool lowerTypedef: false, bool lowerGeneric: false}) {
+ ///
+ /// If [subClass] is set, then we are setting the base class for the given
+ /// class and should emit the given [className], which will already be
+ /// defined.
+ JS.Expression _emitType(DartType type,
+ {bool lowerTypedef: false,
+ bool lowerGeneric: false,
+ ClassElement subClass,
+ JS.Expression className}) {
// The void and dynamic types are not defined in core.
if (type.isVoid) {
return js.call('dart.void');
@@ -2252,11 +2260,16 @@ class CodeGenerator extends GeneralizingAstVisitor
return new JS.Identifier(name);
}
+ if (type == subClass?.type) {
+ return className;
+ }
+
if (type is ParameterizedType) {
var args = type.typeArguments;
Iterable jsArgs = null;
if (args.any((a) => !a.isDynamic)) {
- jsArgs = args.map(_emitTypeName);
+ jsArgs = args.map(
+ (x) => _emitType(x, subClass: subClass, className: className));
} else if (lowerGeneric) {
jsArgs = [];
}
@@ -2537,7 +2550,7 @@ class CodeGenerator extends GeneralizingAstVisitor
f is FunctionType &&
f.typeFormals.isEmpty) {
return _recoverTypeArguments(g, f)
- .map(_emitTypeName)
+ .map(_emitType)
.toList(growable: false);
} else if (typeArgs != null) {
// Dynamic calls may have type arguments, even though the function types
@@ -2979,7 +2992,7 @@ class CodeGenerator extends GeneralizingAstVisitor
JS.Expression _emitConstructorName(
ConstructorElement element, DartType type, SimpleIdentifier name) {
- var typeName = _emitTypeName(type);
+ var typeName = _emitType(type);
if (name != null || element.isFactory) {
var namedCtor = _constructorName(element);
return new JS.PropertyAccess(typeName, namedCtor);
@@ -3005,7 +3018,7 @@ class CodeGenerator extends GeneralizingAstVisitor
if (element == null) {
// TODO(jmesserly): this only happens if we had a static error.
// Should we generate a throw instead?
- ctor = _emitTypeName(type);
+ ctor = _emitType(type);
if (name != null) {
ctor = new JS.PropertyAccess(ctor, _propertyName(name.name));
}
@@ -3931,7 +3944,7 @@ class CodeGenerator extends GeneralizingAstVisitor
return new JS.If(
js.call('dart.is(#, #)', [
_visit(_catchParameter),
- _emitTypeName(clause.exceptionType.type),
+ _emitType(clause.exceptionType.type),
]),
then,
otherwise);
@@ -4021,7 +4034,7 @@ class CodeGenerator extends GeneralizingAstVisitor
// TODO(vsm): When we canonicalize, we need to treat private symbols
// correctly.
var name = js.string(node.components.join('.'), "'");
- return js.call('#.new(#)', [_emitTypeName(types.symbolType), name]);
+ return js.call('#.new(#)', [_emitType(types.symbolType), name]);
}
return _emitConst(emitSymbol);
}
@@ -4039,7 +4052,7 @@ class CodeGenerator extends GeneralizingAstVisitor
if (!elementType.isDynamic) {
// dart.list helper internally depends on _interceptors.JSArray.
_loader.declareBeforeUse(_jsArray);
- list = js.call('dart.list(#, #)', [list, _emitTypeName(elementType)]);
+ list = js.call('dart.list(#, #)', [list, _emitType(elementType)]);
}
return list;
}
@@ -4075,7 +4088,7 @@ class CodeGenerator extends GeneralizingAstVisitor
}
var types = <JS.Expression>[];
if (typeArgs != null) {
- types.addAll(typeArgs.arguments.map((e) => _emitTypeName(e.type)));
+ types.addAll(typeArgs.arguments.map((e) => _emitType(e.type)));
}
return js.call('dart.map(#, #)', [mapArguments, types]);
}
« no previous file with comments | « no previous file | test/codegen/language/generic_self_reference_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698