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

Unified Diff: tests/compiler/dart2js/closure/closure_test.dart

Issue 2999003002: Add more tested features to closure_test (Closed)
Patch Set: Created 3 years, 4 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: tests/compiler/dart2js/closure/closure_test.dart
diff --git a/tests/compiler/dart2js/closure/closure_test.dart b/tests/compiler/dart2js/closure/closure_test.dart
index e1e320d8000b5b2862860354179856fc494a32a3..7447dc6f8df8512f239f9c8448e448ec28f6edb9 100644
--- a/tests/compiler/dart2js/closure/closure_test.dart
+++ b/tests/compiler/dart2js/closure/closure_test.dart
@@ -2,7 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'dart:io';
+import 'dart:io' hide Link;
import 'package:async_helper/async_helper.dart';
import 'package:compiler/src/closure.dart';
import 'package:compiler/src/common.dart';
@@ -14,18 +14,32 @@ import 'package:compiler/src/kernel/element_map.dart';
import 'package:compiler/src/kernel/kernel_backend_strategy.dart';
import 'package:compiler/src/js_model/locals.dart';
import 'package:compiler/src/tree/nodes.dart' as ast;
+import 'package:compiler/src/util/util.dart';
+import 'package:expect/expect.dart';
import '../equivalence/id_equivalence.dart';
import '../equivalence/id_equivalence_helper.dart';
import 'package:kernel/ast.dart' as ir;
-main() {
+main(List<String> args) {
+ bool verbose = args.contains('-v');
asyncTest(() async {
Directory dataDir = new Directory.fromUri(Platform.script.resolve('data'));
await for (FileSystemEntity entity in dataDir.list()) {
+ print('----------------------------------------------------------------');
print('Checking ${entity.uri}');
+ print('----------------------------------------------------------------');
String annotatedCode = await new File.fromUri(entity.uri).readAsString();
- await checkCode(annotatedCode, computeClosureData, compileFromSource);
- await checkCode(annotatedCode, computeKernelClosureData, compileFromDill);
+ print('--from source---------------------------------------------------');
+ await checkCode(annotatedCode, computeClosureData, compileFromSource,
+ verbose: verbose);
+ // TODO(johnnniwinther,efortuna): Enable the these tests for .dill.
+ if (['captured_variable.dart'].contains(entity.uri.pathSegments.last)) {
+ print('--skipped for dill--------------------------------------------');
+ continue;
+ }
+ print('--from dill-----------------------------------------------------');
+ await checkCode(annotatedCode, computeKernelClosureData, compileFromDill,
+ verbose: verbose);
}
});
}
@@ -35,12 +49,14 @@ main() {
/// Fills [actualMap] with the data and [sourceSpanMap] with the source spans
/// for the data origin.
void computeClosureData(Compiler compiler, MemberEntity _member,
- Map<Id, String> actualMap, Map<Id, SourceSpan> sourceSpanMap) {
+ Map<Id, String> actualMap, Map<Id, SourceSpan> sourceSpanMap,
+ {bool verbose: false}) {
MemberElement member = _member;
ClosureDataLookup<ast.Node> closureDataLookup =
compiler.backendStrategy.closureDataLookup as ClosureDataLookup<ast.Node>;
new ClosureAstComputer(compiler.reporter, actualMap, sourceSpanMap,
- member.resolvedAst, closureDataLookup)
+ member.resolvedAst, closureDataLookup,
+ verbose: verbose)
.run();
}
@@ -49,7 +65,8 @@ void computeClosureData(Compiler compiler, MemberEntity _member,
/// Fills [actualMap] with the data and [sourceSpanMap] with the source spans
/// for the data origin.
void computeKernelClosureData(Compiler compiler, MemberEntity member,
- Map<Id, String> actualMap, Map<Id, SourceSpan> sourceSpanMap) {
+ Map<Id, String> actualMap, Map<Id, SourceSpan> sourceSpanMap,
+ {bool verbose: false}) {
KernelBackendStrategy backendStrategy = compiler.backendStrategy;
KernelToElementMapForBuilding elementMap = backendStrategy.elementMap;
GlobalLocalsMap localsMap = backendStrategy.globalLocalsMapForTesting;
@@ -58,30 +75,48 @@ void computeKernelClosureData(Compiler compiler, MemberEntity member,
assert(definition.kind == MemberKind.regular,
failedAt(member, "Unexpected member definition $definition"));
new ClosureIrChecker(actualMap, sourceSpanMap, elementMap, member,
- localsMap.getLocalsMap(member), closureDataLookup)
+ localsMap.getLocalsMap(member), closureDataLookup,
+ verbose: verbose)
.run(definition.node);
}
/// Ast visitor for computing closure data.
-class ClosureAstComputer extends AbstractResolvedAstComputer {
+class ClosureAstComputer extends AbstractResolvedAstComputer
+ with ComputeValueMixin {
final ClosureDataLookup<ast.Node> closureDataLookup;
- final ClosureRepresentationInfo info;
+ final bool verbose;
ClosureAstComputer(
DiagnosticReporter reporter,
Map<Id, String> actualMap,
Map<Id, Spannable> spannableMap,
ResolvedAst resolvedAst,
- this.closureDataLookup)
- : this.info =
- closureDataLookup.getClosureRepresentationInfo(resolvedAst.element),
- super(reporter, actualMap, spannableMap, resolvedAst);
+ this.closureDataLookup,
+ {this.verbose: false})
+ : super(reporter, actualMap, spannableMap, resolvedAst) {
+ push(resolvedAst.element);
+ }
+
+ visitFunctionExpression(ast.FunctionExpression node) {
+ Entity localFunction = resolvedAst.elements.getFunctionDefinition(node);
+ if (localFunction is LocalFunctionElement) {
+ push(localFunction);
+ super.visitFunctionExpression(node);
+ pop();
+ } else {
+ super.visitFunctionExpression(node);
+ }
+ }
@override
String computeNodeValue(ast.Node node, [AstElement element]) {
if (element != null && element.isLocal) {
- LocalElement local = element;
- return computeLocalValue(info, local);
+ if (element.isFunction) {
+ return computeEntityValue(element);
+ } else {
+ LocalElement local = element;
+ return computeLocalValue(local);
+ }
}
// TODO(johnniwinther,efortuna): Collect data for other nodes?
return null;
@@ -91,15 +126,16 @@ class ClosureAstComputer extends AbstractResolvedAstComputer {
String computeElementValue(AstElement element) {
// TODO(johnniwinther,efortuna): Collect data for the member
// (has thisLocal, has box, etc.).
- return null;
+ return computeEntityValue(element);
}
}
/// Kernel IR visitor for computing closure data.
-class ClosureIrChecker extends AbstractIrComputer {
+class ClosureIrChecker extends AbstractIrComputer
+ with ComputeValueMixin<ir.Node> {
final ClosureDataLookup<ir.Node> closureDataLookup;
- final ScopeInfo info;
final KernelToLocalsMap _localsMap;
+ final bool verbose;
ClosureIrChecker(
Map<Id, String> actualMap,
@@ -107,15 +143,31 @@ class ClosureIrChecker extends AbstractIrComputer {
KernelToElementMapForBuilding elementMap,
MemberEntity member,
this._localsMap,
- this.closureDataLookup)
- : this.info = closureDataLookup.getScopeInfo(member),
- super(actualMap, sourceSpanMap);
+ this.closureDataLookup,
+ {this.verbose: false})
+ : super(actualMap, sourceSpanMap) {
+ push(member);
+ }
+
+ visitFunctionExpression(ir.FunctionExpression node) {
+ Local localFunction = _localsMap.getLocalFunction(node);
+ push(localFunction);
+ super.visitFunctionExpression(node);
+ pop();
+ }
+
+ visitFunctionDeclaration(ir.FunctionDeclaration node) {
+ Local localFunction = _localsMap.getLocalFunction(node);
+ push(localFunction);
+ super.visitFunctionDeclaration(node);
+ pop();
+ }
@override
String computeNodeValue(ir.Node node) {
if (node is ir.VariableDeclaration) {
Local local = _localsMap.getLocalVariable(node);
- return computeLocalValue(info, local);
+ return computeLocalValue(local);
}
// TODO(johnniwinther,efortuna): Collect data for other nodes?
return null;
@@ -125,16 +177,150 @@ class ClosureIrChecker extends AbstractIrComputer {
String computeMemberValue(ir.Member member) {
// TODO(johnniwinther,efortuna): Collect data for the member
// (has thisLocal, has box, etc.).
- return null;
+ return computeEntityValue(entity);
}
}
-/// Compute a string representation of the data stored for [local] in [info].
-String computeLocalValue(ScopeInfo info, Local local) {
- StringBuffer sb = new StringBuffer();
- if (info.localIsUsedInTryOrSync(local)) {
- sb.write('inTry');
+abstract class ComputeValueMixin<T> {
+ bool get verbose;
+ ClosureDataLookup<T> get closureDataLookup;
+ Entity get entity => entityStack.head;
+ Link<Entity> entityStack = const Link<Entity>();
+ Link<ScopeInfo> scopeInfoStack = const Link<ScopeInfo>();
+ ScopeInfo get scopeInfo => scopeInfoStack.head;
+ CapturedScope capturedScope;
+ Link<ClosureRepresentationInfo> closureRepresentationInfoStack =
+ const Link<ClosureRepresentationInfo>();
+ ClosureRepresentationInfo get closureRepresentationInfo =>
+ closureRepresentationInfoStack.head;
+
+ void push(Entity entity) {
+ entityStack = entityStack.prepend(entity);
+ scopeInfoStack =
+ scopeInfoStack.prepend(closureDataLookup.getScopeInfo(entity));
+ if (entity is MemberEntity) {
+ capturedScope = closureDataLookup.getCapturedScope(entity);
+ }
+ closureRepresentationInfoStack = closureRepresentationInfoStack.prepend(
+ closureDataLookup.getClosureRepresentationInfoForTesting(entity));
+ dump(entity);
+ }
+
+ void pop() {
+ entityStack = entityStack.tail;
+ scopeInfoStack = scopeInfoStack.tail;
+ closureRepresentationInfoStack = closureRepresentationInfoStack.tail;
+ }
+
+ void dump(Entity entity) {
+ if (!verbose) return;
+
+ print('entity: $entity');
+ print(' scopeInfo (${scopeInfo.runtimeType})');
+ scopeInfo.forEachBoxedVariable((a, b) => print(' boxed1: $a->$b'));
+ print(' capturedScope (${capturedScope.runtimeType})');
+ capturedScope.forEachBoxedVariable((a, b) => print(' boxed2: $a->$b'));
+ print(
+ ' closureRepresentationInfo (${closureRepresentationInfo.runtimeType})');
+ closureRepresentationInfo
+ ?.forEachCapturedVariable((a, b) => print(' captured: $a->$b'));
+ closureRepresentationInfo
+ ?.forEachFreeVariable((a, b) => print(' free3: $a->$b'));
+ closureRepresentationInfo
+ ?.forEachBoxedVariable((a, b) => print(' boxed3: $a->$b'));
+ }
+
+ /// Compute a string representation of the data stored for [local] in [info].
+ String computeLocalValue(Local local) {
+ List<String> features = <String>[];
+ if (scopeInfo.localIsUsedInTryOrSync(local)) {
+ features.add('inTry');
+ // TODO(johnniwinther,efortuna): Should this be enabled and checked?
+ //Expect.isTrue(capturedScope.localIsUsedInTryOrSync(local));
+ } else {
+ //Expect.isFalse(capturedScope.localIsUsedInTryOrSync(local));
+ }
+ if (scopeInfo.isBoxed(local)) {
+ features.add('boxed');
+ Expect.isTrue(capturedScope.isBoxed(local));
+ } else {
+ Expect.isFalse(capturedScope.isBoxed(local));
+ }
+ if (capturedScope.context == local) {
+ features.add('local');
+ }
+ if (capturedScope is CapturedLoopScope) {
+ CapturedLoopScope loopScope = capturedScope;
+ if (loopScope.boxedLoopVariables.contains(local)) {
+ features.add('loop');
+ }
+ }
+ if (closureRepresentationInfo != null) {
+ if (closureRepresentationInfo.createdFieldEntities.contains(local)) {
+ features.add('field');
+ }
+ if (closureRepresentationInfo.isVariableBoxed(local)) {
+ features.add('variable-boxed');
+ }
+ }
+ // TODO(johnniwinther,efortuna): Add more info?
+ return (features.toList()..sort()).join(',');
+ }
+
+ String computeEntityValue(Entity entity) {
+ Map<String, String> features = <String, String>{};
+
+ void addLocals(String name, forEach(f(Local local, _))) {
+ List<String> names = <String>[];
+ forEach((Local local, _) {
+ if (local is BoxLocal) {
+ names.add('box');
+ } else {
+ names.add(local.name);
+ }
+ });
+ String value = names.isEmpty ? null : '[${(names..sort()).join(',')}]';
+ if (features.containsKey(name)) {
+ Expect.equals(
+ features[name], value, "Inconsistent values for $name on $entity.");
+ }
+ features[name] = value;
+ }
+
+ if (scopeInfo.thisLocal != null) {
+ features['hasThis'] = '';
+ }
+ addLocals('boxed', scopeInfo.forEachBoxedVariable);
+
+ if (entity is MemberEntity) {
+ if (capturedScope.requiresContextBox) {
+ features['requiresBox'] = '';
+ }
+ addLocals('boxed', capturedScope.forEachBoxedVariable);
+ }
+
+ if (closureRepresentationInfo != null) {
+ addLocals('boxed', closureRepresentationInfo.forEachBoxedVariable);
+ addLocals('captured', closureRepresentationInfo.forEachCapturedVariable);
+ addLocals('free', closureRepresentationInfo.forEachFreeVariable);
+ }
+
+ StringBuffer sb = new StringBuffer();
+ bool needsComma = false;
+ for (String name in features.keys.toList()..sort()) {
+ String value = features[name];
+ if (value != null) {
+ if (needsComma) {
+ sb.write(',');
+ }
+ sb.write(name);
+ if (value != '') {
+ sb.write('=');
+ sb.write(value);
+ }
+ needsComma = true;
+ }
+ }
+ return sb.toString();
}
- // TODO(johnniwinther,efortuna): Add more info (captured, boxed etc.).
- return sb.toString();
}

Powered by Google App Engine
This is Rietveld 408576698