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

Side by Side Diff: pkg/dev_compiler/lib/src/compiler/code_generator.dart

Issue 3002393002: optimize extension member symbols in DDC, issue #30531 (Closed)
Patch Set: small tweak Created 3 years, 3 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 2
3 // for details. All rights reserved. Use of this source code is governed by a 3 // for details. All rights reserved. Use of this source code is governed by a
4 // BSD-style license that can be found in the LICENSE file. 4 // BSD-style license that can be found in the LICENSE file.
5 5
6 import 'dart:collection' show HashMap, HashSet; 6 import 'dart:collection' show HashMap, HashSet;
7 import 'dart:math' show min, max; 7 import 'dart:math' show min, max;
8 8
9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; 9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator;
10 import 'package:analyzer/dart/ast/ast.dart'; 10 import 'package:analyzer/dart/ast/ast.dart';
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 /// In an async* function, this represents the stream controller parameter. 111 /// In an async* function, this represents the stream controller parameter.
112 JS.TemporaryId _asyncStarController; 112 JS.TemporaryId _asyncStarController;
113 113
114 // TODO(jmesserly): fuse this with notNull check. 114 // TODO(jmesserly): fuse this with notNull check.
115 final _privateNames = 115 final _privateNames =
116 new HashMap<LibraryElement, HashMap<String, JS.TemporaryId>>(); 116 new HashMap<LibraryElement, HashMap<String, JS.TemporaryId>>();
117 final _initializingFormalTemps = 117 final _initializingFormalTemps =
118 new HashMap<ParameterElement, JS.TemporaryId>(); 118 new HashMap<ParameterElement, JS.TemporaryId>();
119 119
120 JS.Identifier _extensionSymbolsModule; 120 JS.Identifier _extensionSymbolsModule;
121 final _extensionSymbols = new Map<String, JS.TemporaryId>();
122
121 JS.Identifier _runtimeModule; 123 JS.Identifier _runtimeModule;
122 final namedArgumentTemp = new JS.TemporaryId('opts'); 124 final namedArgumentTemp = new JS.TemporaryId('opts');
123 125
124 final _hasDeferredSupertype = new HashSet<ClassElement>(); 126 final _hasDeferredSupertype = new HashSet<ClassElement>();
125 127
126 /// The type provider from the current Analysis [context]. 128 /// The type provider from the current Analysis [context].
127 final TypeProvider types; 129 final TypeProvider types;
128 130
129 final LibraryElement dartCoreLibrary; 131 final LibraryElement dartCoreLibrary;
130 final LibraryElement dartJSLibrary; 132 final LibraryElement dartJSLibrary;
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 _extensionSymbolsModule = new JS.Identifier('dartx'); 313 _extensionSymbolsModule = new JS.Identifier('dartx');
312 } else { 314 } else {
313 // Otherwise allow these to be renamed so users can write them. 315 // Otherwise allow these to be renamed so users can write them.
314 _runtimeModule = new JS.TemporaryId('dart'); 316 _runtimeModule = new JS.TemporaryId('dart');
315 _extensionSymbolsModule = new JS.TemporaryId('dartx'); 317 _extensionSymbolsModule = new JS.TemporaryId('dartx');
316 } 318 }
317 _typeTable = new TypeTable(_runtimeModule); 319 _typeTable = new TypeTable(_runtimeModule);
318 320
319 // Initialize our library variables. 321 // Initialize our library variables.
320 var items = <JS.ModuleItem>[]; 322 var items = <JS.ModuleItem>[];
323 var isBuildingSdk = false;
321 for (var unit in compilationUnits) { 324 for (var unit in compilationUnits) {
322 var library = 325 var library =
323 resolutionMap.elementDeclaredByCompilationUnit(unit).library; 326 resolutionMap.elementDeclaredByCompilationUnit(unit).library;
324 if (unit.element != library.definingCompilationUnit) continue; 327 if (unit.element != library.definingCompilationUnit) continue;
325 328
326 var libraryTemp = isSdkInternalRuntime(library) 329 var libraryTemp = isSdkInternalRuntime(library)
327 ? _runtimeModule 330 ? _runtimeModule
328 : new JS.TemporaryId(jsLibraryName(_libraryRoot, library)); 331 : new JS.TemporaryId(jsLibraryName(_libraryRoot, library));
329 _libraries[library] = libraryTemp; 332 _libraries[library] = libraryTemp;
330 items.add(new JS.ExportDeclaration( 333 items.add(new JS.ExportDeclaration(
331 js.call('const # = Object.create(null)', [libraryTemp]))); 334 js.call('const # = Object.create(null)', [libraryTemp])));
332 335
333 // dart:_runtime has a magic module that holds extension method symbols. 336 // dart:_runtime has a magic module that holds extension method symbols.
334 // TODO(jmesserly): find a cleaner design for this. 337 // TODO(jmesserly): find a cleaner design for this.
335 if (isSdkInternalRuntime(library)) { 338 if (isSdkInternalRuntime(library)) {
339 isBuildingSdk = true;
336 items.add(new JS.ExportDeclaration(js 340 items.add(new JS.ExportDeclaration(js
337 .call('const # = Object.create(null)', [_extensionSymbolsModule]))); 341 .call('const # = Object.create(null)', [_extensionSymbolsModule])));
338 } 342 }
339 } 343 }
340 344
341 // Collect all class/type Element -> Node mappings 345 // Collect all class/type Element -> Node mappings
342 // in case we need to forward declare any classes. 346 // in case we need to forward declare any classes.
343 _declarationNodes = new HashMap<TypeDefiningElement, AstNode>.identity(); 347 _declarationNodes = new HashMap<TypeDefiningElement, AstNode>.identity();
344 for (var unit in compilationUnits) { 348 for (var unit in compilationUnits) {
345 for (var declaration in unit.declarations) { 349 for (var declaration in unit.declarations) {
(...skipping 19 matching lines...) Expand all
365 // Order will be changed as needed so the resulting code can execute. 369 // Order will be changed as needed so the resulting code can execute.
366 // This is done by forward declaring items. 370 // This is done by forward declaring items.
367 compilationUnits.forEach(visitCompilationUnit); 371 compilationUnits.forEach(visitCompilationUnit);
368 assert(_deferredProperties.isEmpty); 372 assert(_deferredProperties.isEmpty);
369 373
370 // Visit directives (for exports) 374 // Visit directives (for exports)
371 compilationUnits.forEach(_emitExportDirectives); 375 compilationUnits.forEach(_emitExportDirectives);
372 376
373 // Declare imports 377 // Declare imports
374 _finishImports(items); 378 _finishImports(items);
379 // Initialize extension symbols
380 _extensionSymbols.forEach((name, id) {
381 var value =
382 new JS.PropertyAccess(_extensionSymbolsModule, _propertyName(name));
383 if (isBuildingSdk) {
384 value = js.call('# = Symbol(#)', [value, js.string("dartx.$name")]);
385 }
386 items.add(js.statement('const # = #;', [id, value]));
387 });
375 388
376 // Discharge the type table cache variables and 389 // Discharge the type table cache variables and
377 // hoisted definitions. 390 // hoisted definitions.
378 items.addAll(_typeTable.discharge()); 391 items.addAll(_typeTable.discharge());
379 items.addAll(_internalSdkFunctions); 392 items.addAll(_internalSdkFunctions);
380 393
381 // Track the module name for each library in the module. 394 // Track the module name for each library in the module.
382 // This data is only required for debugging. 395 // This data is only required for debugging.
383 _moduleItems.add(js.statement( 396 _moduleItems.add(js.statement(
384 '#.trackLibraries(#, #, ${JSModuleFile.sourceMapHoleID});', 397 '#.trackLibraries(#, #, ${JSModuleFile.sourceMapHoleID});',
(...skipping 541 matching lines...) Expand 10 before | Expand all | Expand 10 after
926 virtualFields, 939 virtualFields,
927 classElem, 940 classElem,
928 getClassCovariantParameters(node), 941 getClassCovariantParameters(node),
929 _usedCovariantPrivateMembers); 942 _usedCovariantPrivateMembers);
930 943
931 var jsCtors = _defineConstructors(classElem, className, fields, ctors); 944 var jsCtors = _defineConstructors(classElem, className, fields, ctors);
932 var classExpr = _emitClassExpression(classElem, _emitClassMethods(node), 945 var classExpr = _emitClassExpression(classElem, _emitClassMethods(node),
933 fields: allFields); 946 fields: allFields);
934 947
935 var body = <JS.Statement>[]; 948 var body = <JS.Statement>[];
936 _initExtensionSymbols(classElem, methods, fields, body);
937 _emitSuperHelperSymbols(body); 949 _emitSuperHelperSymbols(body);
938 950
939 // Emit the class, e.g. `core.Object = class Object { ... }` 951 // Emit the class, e.g. `core.Object = class Object { ... }`
940 _defineClass(classElem, className, classExpr, body); 952 _defineClass(classElem, className, classExpr, body);
941 body.addAll(jsCtors); 953 body.addAll(jsCtors);
942 954
943 // Emit things that come after the ES6 `class ... { ... }`. 955 // Emit things that come after the ES6 `class ... { ... }`.
944 var jsPeerNames = _getJSPeerNames(classElem); 956 var jsPeerNames = _getJSPeerNames(classElem);
945 JS.Statement deferredBaseClass = 957 JS.Statement deferredBaseClass =
946 _setBaseClass(classElem, className, jsPeerNames, body); 958 _setBaseClass(classElem, className, jsPeerNames, body);
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
1171 // Define the type tests on the default instantiation to check for that 1183 // Define the type tests on the default instantiation to check for that
1172 // marker. 1184 // marker.
1173 var defaultInst = _emitTopLevelName(classElem); 1185 var defaultInst = _emitTopLevelName(classElem);
1174 1186
1175 // Return this `addTypeTests` call so we can emit it outside of the generic 1187 // Return this `addTypeTests` call so we can emit it outside of the generic
1176 // type parameter scope. 1188 // type parameter scope.
1177 return _callHelperStatement( 1189 return _callHelperStatement(
1178 'addTypeTests(#, #);', [defaultInst, isClassSymbol]); 1190 'addTypeTests(#, #);', [defaultInst, isClassSymbol]);
1179 } 1191 }
1180 1192
1181 void _emitSuperHelperSymbols(List<JS.Statement> body) { 1193 void _emitSymbols(Iterable<JS.TemporaryId> vars, List<JS.ModuleItem> body) {
1182 for (var id in _superHelpers.values.map((m) => m.name as JS.TemporaryId)) { 1194 for (var id in vars) {
1183 body.add(js.statement('const # = Symbol(#)', [id, js.string(id.name)])); 1195 body.add(js.statement('const # = Symbol(#)', [id, js.string(id.name)]));
1184 } 1196 }
1197 }
1198
1199 void _emitSuperHelperSymbols(List<JS.Statement> body) {
1200 _emitSymbols(
1201 _superHelpers.values.map((m) => m.name as JS.TemporaryId), body);
1185 _superHelpers.clear(); 1202 _superHelpers.clear();
1186 } 1203 }
1187 1204
1188 void _emitVirtualFieldSymbols( 1205 void _emitVirtualFieldSymbols(
1189 ClassElement classElement, List<JS.Statement> body) { 1206 ClassElement classElement, List<JS.Statement> body) {
1190 _classProperties.virtualFields.forEach((field, virtualField) { 1207 _classProperties.virtualFields.forEach((field, virtualField) {
1191 body.add(js.statement('const # = Symbol(#);', 1208 body.add(js.statement('const # = Symbol(#);',
1192 [virtualField, js.string('${classElement.name}.${field.name}')])); 1209 [virtualField, js.string('${classElement.name}.${field.name}')]));
1193 }); 1210 });
1194 } 1211 }
(...skipping 953 matching lines...) Expand 10 before | Expand all | Expand 10 after
2148 body.add(_callHelperStatement('setSignature(#, #);', [className, sig])); 2165 body.add(_callHelperStatement('setSignature(#, #);', [className, sig]));
2149 } 2166 }
2150 // Add static property dart._runtimeType to Object. 2167 // Add static property dart._runtimeType to Object.
2151 // All other Dart classes will (statically) inherit this property. 2168 // All other Dart classes will (statically) inherit this property.
2152 if (classElem == objectClass) { 2169 if (classElem == objectClass) {
2153 body.add(_callHelperStatement('tagComputed(#, () => #.#);', 2170 body.add(_callHelperStatement('tagComputed(#, () => #.#);',
2154 [className, emitLibraryName(dartCoreLibrary), 'Type'])); 2171 [className, emitLibraryName(dartCoreLibrary), 'Type']));
2155 } 2172 }
2156 } 2173 }
2157 2174
2158 /// Ensure `dartx.` symbols we will use are present.
2159 void _initExtensionSymbols(
2160 ClassElement classElem,
2161 List<MethodDeclaration> methods,
2162 List<FieldDeclaration> fields,
2163 List<JS.Statement> body) {
2164 if (_extensionTypes.hasNativeSubtype(classElem.type)) {
2165 var dartxNames = <JS.Expression>[];
2166 for (var m in methods) {
2167 if (!m.isAbstract &&
2168 !m.isStatic &&
2169 resolutionMap.elementDeclaredByMethodDeclaration(m).isPublic) {
2170 dartxNames.add(_declareMemberName(m.element, useExtension: false));
2171 }
2172 }
2173 for (var fieldDecl in fields) {
2174 if (!fieldDecl.isStatic) {
2175 for (var field in fieldDecl.fields.variables) {
2176 var e = field.element as FieldElement;
2177 if (e.isPublic) {
2178 dartxNames.add(_declareMemberName(e.getter, useExtension: false));
2179 }
2180 }
2181 }
2182 }
2183 if (dartxNames.isNotEmpty) {
2184 body.add(_callHelperStatement('defineExtensionNames(#)',
2185 [new JS.ArrayInitializer(dartxNames, multiline: true)]));
2186 }
2187 }
2188 }
2189
2190 JS.Expression _emitConstructor(ConstructorDeclaration node, 2175 JS.Expression _emitConstructor(ConstructorDeclaration node,
2191 List<FieldDeclaration> fields, bool isCallable, JS.Expression className) { 2176 List<FieldDeclaration> fields, bool isCallable, JS.Expression className) {
2192 var params = _emitFormalParameterList(node.parameters); 2177 var params = _emitFormalParameterList(node.parameters);
2193 2178
2194 var savedFunction = _currentFunction; 2179 var savedFunction = _currentFunction;
2195 _currentFunction = node.body; 2180 _currentFunction = node.body;
2196 2181
2197 var savedSuperAllowed = _superAllowed; 2182 var savedSuperAllowed = _superAllowed;
2198 _superAllowed = false; 2183 _superAllowed = false;
2199 var body = _emitConstructorBody(node, fields, className); 2184 var body = _emitConstructorBody(node, fields, className);
(...skipping 3447 matching lines...) Expand 10 before | Expand all | Expand 10 after
5647 break; 5632 break;
5648 case 'unary-': 5633 case 'unary-':
5649 name = '_negate'; 5634 name = '_negate';
5650 break; 5635 break;
5651 case 'constructor': 5636 case 'constructor':
5652 case 'prototype': 5637 case 'prototype':
5653 name = '_$name'; 5638 name = '_$name';
5654 break; 5639 break;
5655 } 5640 }
5656 5641
5657 var result = _propertyName(name); 5642 if (useExtension ?? _isSymbolizedMember(type, name)) {
5658 5643 return _extensionSymbols.putIfAbsent(name,
5659 useExtension ??= _isSymbolizedMember(type, name); 5644 () => new JS.TemporaryId('\$${_friendlyOperatorName[name] ?? name}'));
5660 5645 }
5661 return useExtension 5646 return _propertyName(name);
5662 ? js.call('#.#', [_extensionSymbolsModule, result])
5663 : result;
5664 } 5647 }
5665 5648
5666 var _forwardingCache = new HashMap<Element, Map<String, ExecutableElement>>(); 5649 var _forwardingCache = new HashMap<Element, Map<String, ExecutableElement>>();
5667 5650
5668 Element _lookupForwardedMember(ClassElement element, String name) { 5651 Element _lookupForwardedMember(ClassElement element, String name) {
5669 // We only care about public methods. 5652 // We only care about public methods.
5670 if (name.startsWith('_')) return null; 5653 if (name.startsWith('_')) return null;
5671 5654
5672 var map = _forwardingCache.putIfAbsent(element, () => {}); 5655 var map = _forwardingCache.putIfAbsent(element, () => {});
5673 if (map.containsKey(name)) return map[name]; 5656 if (map.containsKey(name)) return map[name];
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after
6065 // The library the prefix is referring to must come from a deferred import. 6048 // The library the prefix is referring to must come from a deferred import.
6066 var containingLibrary = resolutionMap 6049 var containingLibrary = resolutionMap
6067 .elementDeclaredByCompilationUnit(target.root as CompilationUnit) 6050 .elementDeclaredByCompilationUnit(target.root as CompilationUnit)
6068 .library; 6051 .library;
6069 var imports = containingLibrary.getImportsWithPrefix(prefix); 6052 var imports = containingLibrary.getImportsWithPrefix(prefix);
6070 return imports.length == 1 && imports[0].isDeferred; 6053 return imports.length == 1 && imports[0].isDeferred;
6071 } 6054 }
6072 6055
6073 bool _annotatedNullCheck(Element e) => 6056 bool _annotatedNullCheck(Element e) =>
6074 e != null && findAnnotation(e, isNullCheckAnnotation) != null; 6057 e != null && findAnnotation(e, isNullCheckAnnotation) != null;
6058
6059 final _friendlyOperatorName = {
6060 '<': 'lessThan',
6061 '>': 'greaterThan',
6062 '<=': 'lessOrEquals',
6063 '>=': 'greaterOrEquals',
6064 '==': 'equals',
6065 '-': 'minus',
6066 '+': 'plus',
6067 '/': 'divide',
6068 '~/': 'floorDivide',
6069 '*': 'times',
6070 '%': 'modulo',
6071 '|': 'bitOr',
6072 '^': 'bitXor',
6073 '&': 'bitAnd',
6074 '<<': 'leftShift',
6075 '>>': 'rightShift',
6076 '~': 'bitNot'
6077 };
OLDNEW
« no previous file with comments | « pkg/dev_compiler/lib/sdk/ddc_sdk.sum ('k') | pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698