Emit constants during expression compilation to js

Closes: https://github.com/dart-lang/sdk/issues/43963
Change-Id: Ic8af046b2cf1506984b84ea66b2676b3cc0f1771
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/169580
Commit-Queue: Anna Gringauze <annagrin@google.com>
Reviewed-by: Nicholas Shahan <nshahan@google.com>
This commit is contained in:
Anna Gringauze 2020-11-02 20:03:14 +00:00 committed by commit-bot@chromium.org
parent 3eb34ef646
commit 42dc617ee8
2 changed files with 80 additions and 3 deletions

View file

@ -3002,12 +3002,49 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
// size on expression evaluation is better.
// Issue: https://github.com/dart-lang/sdk/issues/43288
var fun = _emitFunction(functionNode, name);
var items = _typeTable?.discharge();
var body = js_ast.Block([...?items, ...fun.body.statements]);
var types = _typeTable.discharge();
var constants = _dischargeConstTable();
var body = js_ast.Block([...?types, ...?constants, ...fun.body.statements]);
return js_ast.Fun(fun.params, body);
}
/// Emit all collected const symbols
///
/// This is similar to how constants are emitted during
/// initial compilation in emitModule
///
/// TODO: unify the code with emitModule.
List<js_ast.Statement> _dischargeConstTable() {
var items = <js_ast.Statement>[];
if (_constLazyAccessors.isNotEmpty) {
var constTableBody = runtimeStatement(
'defineLazy(#, { # }, false)', [_constTable, _constLazyAccessors]);
items.add(constTableBody);
_constLazyAccessors.clear();
}
_copyAndFlattenBlocks(items, moduleItems);
moduleItems.clear();
return items;
}
/// Flattens blocks in [items] to a single list.
///
/// This will not flatten blocks that are marked as being scopes.
void _copyAndFlattenBlocks(
List<js_ast.Statement> result, Iterable<js_ast.ModuleItem> items) {
for (var item in items) {
if (item is js_ast.Block && !item.isScope) {
_copyAndFlattenBlocks(result, item.statements);
} else {
result.add(item as js_ast.Statement);
}
}
}
js_ast.Fun _emitFunction(FunctionNode f, String name) {
// normal function (sync), vs (sync*, async, async*)
var isSync = f.asyncMarker == AsyncMarker.Sync;

View file

@ -409,6 +409,28 @@ void main() {
))
''');
});
test('function', () async {
await driver.check(
scope: <String, String>{'x': '1', 'y': '2', 'z': '3'},
expression: 'main',
expectedResult: '''
(function(x, y, z) {
var VoidTodynamic = () => (VoidTodynamic = dart.constFn(dart.fnType(dart.dynamic, [])))();
dart.defineLazy(CT, {
get C0() {
return C0 = dart.fn(foo.main, VoidTodynamic());
}
}, false);
var C0;
return C0 || CT.C0;
}(
1,
2,
3
))
''');
});
});
group('Expression compiler tests in method:', () {
@ -1313,7 +1335,16 @@ void main() {
expression: 'const MyClass(1)',
expectedResult: '''
(function(p) {
return C0 || CT.C0;
dart.defineLazy(CT, {
get C0() {
return C0 = dart.const({
__proto__: foo.MyClass.prototype,
[_t]: 1
});
}
}, false);
var C0;
return C0 || CT.C0;
}(
1
))
@ -1353,6 +1384,15 @@ void main() {
expression: "const Key('t')",
expectedResult: '''
(function(p) {
dart.defineLazy(CT, {
get C0() {
return C0 = dart.const({
__proto__: foo.ValueKey.prototype,
[value]: "t"
});
}
}, false);
var C0;
return C0 || CT.C0;
}(
1