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

Unified Diff: lib/src/codegen/js_codegen.dart

Issue 1100633006: Generate static calls for Object fields and methods (Closed) Base URL: https://github.com/dart-lang/dev_compiler.git@master
Patch Set: Created 5 years, 8 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
Index: lib/src/codegen/js_codegen.dart
diff --git a/lib/src/codegen/js_codegen.dart b/lib/src/codegen/js_codegen.dart
index 85b42aa56d42f9ca351932e4bee14d862c65b40a..02e2113d3ddef31f447c05d1bfe057fb8ab5ca56 100644
--- a/lib/src/codegen/js_codegen.dart
+++ b/lib/src/codegen/js_codegen.dart
@@ -68,6 +68,9 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
ConstantEvaluator _constEvaluator;
+ /// Map of fields / properties / methods on Object.
+ Map<String, DartType> _objectMembers;
+
final _exports = new Set<String>();
final _lazyFields = <VariableDeclaration>[];
final _properties = <FunctionDeclaration>[];
@@ -94,7 +97,9 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
final _libraryCycleMemo = new HashMap<LibraryElement, bool>();
JSCodegenVisitor(this.options, this.rules, this.libraryInfo,
- this._extensionMethods, this._fieldsNeedingStorage);
+ this._extensionMethods, this._fieldsNeedingStorage) {
+ _objectMembers = getObjectMemberMap(rules.provider);
Jennifer Messerly 2015/04/23 19:01:42 thought here, TypeRules is our type (src/checker/r
vsm 2015/04/23 20:35:55 Yeah, I suppose that's better than here. Done.
+ }
LibraryElement get currentLibrary => libraryInfo.library;
TypeProvider get types => rules.provider;
@@ -185,10 +190,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
var code = _visit(child);
if (code != null) {
- if (_pendingStatements.isNotEmpty) {
- body.addAll(_pendingStatements);
- _pendingStatements.clear();
- }
+ _flushPendingStatements(body);
body.add(code);
}
}
@@ -1126,7 +1128,6 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
var element = type.element;
if (name == '' || lowerTypedef && type is FunctionType) {
if (type is FunctionType) {
- // TODO(vsm): Support all parameter types.
var returnType = type.returnType;
var parameterTypes = type.normalParameterTypes;
var optionalTypes = type.optionalParameterTypes;
@@ -1276,6 +1277,10 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
code, [_visit(node.methodName), _visit(node.argumentList)]);
}
+ var type = getStaticType(target);
+ var name = node.methodName.name;
+ var memberName = _emitMemberName(name, type: type);
+
if (rules.isDynamicTarget(target)) {
code = 'dart.$DSEND(#, #, #)';
} else if (rules.isDynamicCall(node.methodName)) {
@@ -1283,14 +1288,20 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
// class Foo { Function bar; }
// new Foo().bar(); // dynamic call
code = 'dart.$DCALL(#.#, #)';
+ } else if (_objectMembers.containsKey(name)) {
Jennifer Messerly 2015/04/23 19:05:58 Is this only if `target` is nullable**? A test cas
vsm 2015/04/23 20:35:55 I added a check in. We need both checks as all ty
+ assert(_objectMembers[name] is FunctionType);
+ // Object methods require a helper for null checks.
+ return js.call('dart.#(#, #)', [
+ memberName,
+ _visit(target),
+ _visit(node.argumentList)
+ ]);
} else {
code = '#.#(#)';
}
- return js.call(code, [
- _visit(target),
- _emitMemberName(node.methodName.name, type: getStaticType(target)),
- _visit(node.argumentList)
- ]);
+
+ return js.call(
+ code, [_visit(target), memberName, _visit(node.argumentList)]);
}
/// Emits code for the `JS(...)` builtin.
@@ -1442,9 +1453,20 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
return value != null ? value : new JS.LiteralNull();
}
+ void _flushPendingStatements(List<JS.Statement> body) {
+ if (_pendingStatements.isNotEmpty) {
+ body.addAll(_pendingStatements);
+ _pendingStatements.clear();
+ }
+ }
+
void _flushLazyFields(List<JS.Statement> body) {
var code = _emitLazyFields(_exportsVar, _lazyFields);
- if (code != null) body.add(code);
+ if (code != null) {
+ // Ensure symbols for private fields are defined.
+ _flushPendingStatements(body);
+ body.add(code);
+ }
_lazyFields.clear();
}
@@ -1455,14 +1477,16 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
var methods = [];
for (var node in fields) {
var name = node.name.name;
- methods.add(new JS.Method(_propertyName(name),
- js.call('function() { return #; }', _visit(node.initializer)),
+ var element = node.element;
+ var access = _emitMemberName(name, type: element.type, isStatic: true);
+ methods.add(new JS.Method(
+ access, js.call('function() { return #; }', _visit(node.initializer)),
isGetter: true));
// TODO(jmesserly): use a dummy setter to indicate writable.
if (!node.isFinal) {
- methods.add(new JS.Method(
- _propertyName(name), js.call('function(_) {}'), isSetter: true));
+ methods.add(
+ new JS.Method(access, js.call('function(_) {}'), isSetter: true));
}
}
@@ -1876,10 +1900,14 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
var member = memberId.staticElement;
if (member != null && member is MethodElement) {
// Tear-off methods: explicitly bind it.
- if (isStateless(target, target)) {
+ if (isStateless(target, target) &&
+ !_objectMembers.containsKey(memberId.name)) {
return js.call('#.#.bind(#)', [_visit(target), name, _visit(target)]);
}
code = 'dart.bind(#, #)';
+ } else if (_objectMembers.containsKey(memberId.name)) {
+ code = 'dart.#(#)';
+ return js.call(code, [name, _visit(target)]);
} else {
code = '#.#';
}

Powered by Google App Engine
This is Rietveld 408576698