Skip to content

Commit 1265dc4

Browse files
author
John Messerly
committed
fix #569, cache constants defined in methods
R=leafp@google.com, sra@google.com Review URL: https://codereview.chromium.org/1979013003 .
1 parent 3c44af0 commit 1265dc4

File tree

6 files changed

+160
-57
lines changed

6 files changed

+160
-57
lines changed

pkg/dev_compiler/lib/runtime/dart_sdk.js

+110-50
Large diffs are not rendered by default.

pkg/dev_compiler/lib/src/compiler/code_generator.dart

+19-3
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ class CodeGenerator extends GeneralizingAstVisitor
127127
List<JS.TemporaryId> _superHelperSymbols = <JS.TemporaryId>[];
128128
List<JS.Method> _superHelpers = <JS.Method>[];
129129

130+
List<TypeParameterType> _typeParamInConst = null;
131+
130132
/// Whether we are currently generating code for the body of a `JS()` call.
131133
bool _isInForeignJS = false;
132134

@@ -2307,6 +2309,7 @@ class CodeGenerator extends GeneralizingAstVisitor
23072309
}
23082310

23092311
if (type is TypeParameterType) {
2312+
_typeParamInConst?.add(type);
23102313
return new JS.Identifier(name);
23112314
}
23122315

@@ -3392,9 +3395,22 @@ class CodeGenerator extends GeneralizingAstVisitor
33923395
}
33933396

33943397
JS.Expression _emitConst(JS.Expression expr()) {
3395-
// TODO(jmesserly): emit the constants at top level if possible.
3396-
// This wasn't quite working, so disabled for now.
3397-
return js.call('dart.const(#)', expr());
3398+
var savedTypeParams = _typeParamInConst;
3399+
_typeParamInConst = [];
3400+
3401+
var jsExpr = js.call('dart.const(#)', expr());
3402+
3403+
bool usesTypeParams = _typeParamInConst.isNotEmpty;
3404+
_typeParamInConst = savedTypeParams;
3405+
3406+
// TODO(jmesserly): if it uses type params we can still hoist it up as far
3407+
// as it will go, e.g. at the level the generic class is defined where type
3408+
// params are available.
3409+
if (_currentFunction == null || usesTypeParams) return jsExpr;
3410+
3411+
var temp = new JS.TemporaryId('const');
3412+
_moduleItems.add(js.statement('let #;', [temp]));
3413+
return js.call('# || (# = #)', [temp, temp, jsExpr]);
33983414
}
33993415

34003416
/// Returns a new expression, which can be be used safely *once* on the

pkg/dev_compiler/lib/src/compiler/element_helpers.dart

+20-2
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,16 @@
55
/// Helpers for Analyzer's Element model and corelib model.
66
77
import 'package:analyzer/dart/ast/ast.dart'
8-
show Expression, MethodInvocation, SimpleIdentifier;
8+
show
9+
ConstructorDeclaration,
10+
Expression,
11+
FunctionBody,
12+
FunctionExpression,
13+
MethodDeclaration,
14+
MethodInvocation,
15+
SimpleIdentifier;
916
import 'package:analyzer/dart/element/element.dart'
10-
show Element, FunctionElement;
17+
show Element, ExecutableElement, FunctionElement;
1118
import 'package:analyzer/dart/element/type.dart'
1219
show DartType, InterfaceType, ParameterizedType;
1320
import 'package:analyzer/src/dart/element/type.dart' show DynamicTypeImpl;
@@ -82,6 +89,17 @@ bool isInlineJS(Element e) =>
8289
e.library.isInSdk &&
8390
e.library.source.uri.toString() == 'dart:_foreign_helper';
8491

92+
ExecutableElement getFunctionBodyElement(FunctionBody body) {
93+
var f = body.parent;
94+
if (f is FunctionExpression) {
95+
return f.element;
96+
} else if (f is MethodDeclaration) {
97+
return f.element;
98+
} else {
99+
return (f as ConstructorDeclaration).element;
100+
}
101+
}
102+
85103
/// Returns the value of the `name` field from the [match]ing annotation on
86104
/// [element], or `null` if we didn't find a valid match or it was not a string.
87105
///

pkg/dev_compiler/lib/src/compiler/module_builder.dart

+5-1
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,11 @@ class NodeModuleBuilder extends _ModuleBuilder {
150150

151151
/// Escape [name] to make it into a valid identifier.
152152
String pathToJSIdentifier(String name) {
153-
name = path.basenameWithoutExtension(name);
153+
return toJSIdentifier(path.basenameWithoutExtension(name));
154+
}
155+
156+
/// Escape [name] to make it into a valid identifier.
157+
String toJSIdentifier(String name) {
154158
if (name.length == 0) return r'$';
155159

156160
// Escape any invalid characters

pkg/dev_compiler/test/browser/language_tests.js

+4
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,10 @@
466466
'chunked_conversion_utf8_test': skip_timeout,
467467
'encoding_test': skip_timeout,
468468

469+
// TODO(jmesserly): this is in an inconsistent state between our old and
470+
// newer SDKs.
471+
'html_escape_test': skip_fail,
472+
469473
// TODO(rnystrom): If this test is enabled, karma gets confused and
470474
// disconnects randomly.
471475
'json_lib_test': skip_fail,

pkg/dev_compiler/test/codegen/expect/DeltaBlue.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,14 @@ dart_library.library('DeltaBlue', null, /* Imports */[
8181
dart.setSignature(DeltaBlue$.DeltaBlue, {
8282
constructors: () => ({DeltaBlue: [DeltaBlue$.DeltaBlue, []]})
8383
});
84+
let const$;
8485
DeltaBlue$.Strength = class Strength extends core.Object {
8586
Strength(value, name) {
8687
this.value = value;
8788
this.name = name;
8889
}
8990
nextWeaker() {
90-
return dart.const(dart.list([DeltaBlue$.STRONG_PREFERRED, DeltaBlue$.PREFERRED, DeltaBlue$.STRONG_DEFAULT, DeltaBlue$.NORMAL, DeltaBlue$.WEAK_DEFAULT, DeltaBlue$.WEAKEST], DeltaBlue$.Strength))[dartx.get](this.value);
91+
return (const$ || (const$ = dart.const(dart.list([DeltaBlue$.STRONG_PREFERRED, DeltaBlue$.PREFERRED, DeltaBlue$.STRONG_DEFAULT, DeltaBlue$.NORMAL, DeltaBlue$.WEAK_DEFAULT, DeltaBlue$.WEAKEST], DeltaBlue$.Strength))))[dartx.get](this.value);
9192
}
9293
static stronger(s1, s2) {
9394
return dart.notNull(s1.value) < dart.notNull(s2.value);

0 commit comments

Comments
 (0)