Skip to content

Commit

Permalink
[ddc] Tag classes with names of static members
Browse files Browse the repository at this point in the history
Temporarily add names of static members so they can be accessed by the
debugger. Eventually, these will be accessible through the symbol data
and should be removed from the compiled Javascript.

This increases the size of the compiled output by ~1% in a large
google3 application.

Names and types of static members were originally removed from the
compiled output in https://dart-review.googlesource.com/c/sdk/+/48455
because they are not needed for runtime correctness.


Change-Id: Idfd827ececec80d903586917676ec027e2a5a9e8
Issue: #40273
Issue: dart-lang/webdev#1430
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/217501
Reviewed-by: Anna Gringauze <[email protected]>
Commit-Queue: Nicholas Shahan <[email protected]>
  • Loading branch information
nshahan authored and [email protected] committed Oct 25, 2021
1 parent 76dadee commit cc9353a
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 29 deletions.
49 changes: 37 additions & 12 deletions pkg/dev_compiler/lib/src/kernel/compiler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1395,16 +1395,26 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
void emitSignature(String name, List<js_ast.Property> elements) {
if (elements.isEmpty) return;

js_ast.Statement setSignature;
if (!name.startsWith('Static')) {
var proto = c == _coreTypes.objectClass
? js.call('Object.create(null)')
: runtimeCall('get${name}s(#.__proto__)', [className]);
elements.insert(0, js_ast.Property(propertyName('__proto__'), proto));
setSignature = runtimeStatement('set${name}Signature(#, () => #)', [
className,
js_ast.ObjectInitializer(elements, multiline: elements.length > 1)
]);
} else {
// TODO(40273) Only tagging with the names of static members until the
// debugger consumes signature information from symbol files.
setSignature = runtimeStatement('set${name}Signature(#, () => #)', [
className,
js_ast.ArrayInitializer(elements.map((e) => e.name).toList())
]);
}
body.add(runtimeStatement('set${name}Signature(#, () => #)', [
className,
js_ast.ObjectInitializer(elements, multiline: elements.length > 1)
]));

body.add(setSignature);
}

var extMethods = _classProperties.extensionMethods;
Expand All @@ -1416,6 +1426,8 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
var staticSetters = <js_ast.Property>[];
var instanceSetters = <js_ast.Property>[];
List<js_ast.Property> getSignatureList(Procedure p) {
// TODO(40273) Skip for all statics when the debugger consumes signature
// information from symbol files.
if (p.isStatic) {
if (p.isGetter) {
return staticGetters;
Expand All @@ -1437,9 +1449,14 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>

var classProcedures = c.procedures.where((p) => !p.isAbstract).toList();
for (var member in classProcedures) {
// Static getters/setters/methods cannot be called with dynamic dispatch,
// nor can they be torn off.
if (member.isStatic) continue;
// Static getters/setters cannot be called with dynamic dispatch or torn
// off. Static methods can't be called with dynamic dispatch and are
// tagged with a type when torn off. Most are implicitly const and
// canonicalized. Static signatures are only used by the debugger and are
// not needed for runtime correctness.
// TODO(40273) Skip for all statics when the debugger consumes signature
// information from symbol files.
if (isTearOffLowering(member)) continue;

var name = member.name.text;
var reifiedType = _memberRuntimeType(member, c) as FunctionType;
Expand Down Expand Up @@ -1478,6 +1495,8 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
}

emitSignature('Method', instanceMethods);
// TODO(40273) Skip for all statics when the debugger consumes signature
// information from symbol files.
emitSignature('StaticMethod', staticMethods);
emitSignature('Getter', instanceGetters);
emitSignature('Setter', instanceSetters);
Expand All @@ -1491,16 +1510,19 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>

var classFields = c.fields.toList();
for (var field in classFields) {
// Only instance fields need to be saved for dynamic dispatch.
var isStatic = field.isStatic;
if (isStatic) continue;

// Static fields cannot be called with dynamic dispatch or torn off. The
// signatures are only used by the debugger and are not needed for runtime
// correctness.
var memberName = _declareMemberName(field);
var fieldSig = _emitFieldSignature(field, c);
(isStatic ? staticFields : instanceFields)
// TODO(40273) Skip static fields when the debugger consumes signature
// information from symbol files.
(field.isStatic ? staticFields : instanceFields)
.add(js_ast.Property(memberName, fieldSig));
}
emitSignature('Field', instanceFields);
// TODO(40273) Skip for all statics when the debugger consumes signature
// information from symbol files.
emitSignature('StaticField', staticFields);

// Add static property dart._runtimeType to Object.
Expand Down Expand Up @@ -2525,6 +2547,9 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
var exportName = _jsExportName(member);
if (exportName != null) return propertyName(exportName);
}
if (member is Procedure && member.isFactory) {
return _constructorName(member.name.text);
}
switch (name) {
// Reserved for the compiler to do `x as T`.
case 'as':
Expand Down
20 changes: 3 additions & 17 deletions sdk/lib/_internal/js_dev_runtime/private/debugger.dart
Original file line number Diff line number Diff line change
Expand Up @@ -924,23 +924,9 @@ class ClassFormatter implements Formatter {
// implemented interfaces, and methods.
var ret = LinkedHashSet<NameValuePair>();

var staticProperties = Set<NameValuePair>();
var staticMethods = Set<NameValuePair>();
// Static fields and properties.
addPropertiesFromSignature(
dart.getStaticFields(type), staticProperties, type, false);
addPropertiesFromSignature(
dart.getStaticGetters(type), staticProperties, type, false);
// static methods.
addPropertiesFromSignature(
dart.getStaticMethods(type), staticMethods, type, false);

if (staticProperties.isNotEmpty || staticMethods.isNotEmpty) {
ret
..add(NameValuePair(value: '[[Static members]]', hideName: true))
..addAll(sortProperties(staticProperties))
..addAll(sortProperties(staticMethods));
}
// Static fields, getters, setters, and methods signatures were removed
// from the runtime representation because they are not needed. At this
// time there is no intention to support them in this custom formatter.

// instance methods.
var instanceMethods = Set<NameValuePair>();
Expand Down

0 comments on commit cc9353a

Please sign in to comment.