| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 // Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file | 
|  | 2 // for details. All rights reserved. Use of this source code is governed by a | 
|  | 3 // BSD-style license that can be found in the LICENSE file. | 
|  | 4 | 
|  | 5 import 'dart:io'; | 
|  | 6 import 'package:async_helper/async_helper.dart'; | 
|  | 7 import 'package:compiler/src/common.dart'; | 
|  | 8 import 'package:compiler/src/compiler.dart'; | 
|  | 9 import 'package:compiler/src/diagnostics/diagnostic_listener.dart'; | 
|  | 10 import 'package:compiler/src/elements/elements.dart'; | 
|  | 11 import 'package:compiler/src/elements/entities.dart'; | 
|  | 12 import 'package:compiler/src/elements/jumps.dart'; | 
|  | 13 import 'package:compiler/src/js_model/locals.dart'; | 
|  | 14 import 'package:compiler/src/kernel/element_map.dart'; | 
|  | 15 import 'package:compiler/src/kernel/kernel_backend_strategy.dart'; | 
|  | 16 import 'package:compiler/src/tree/nodes.dart' as ast; | 
|  | 17 import '../equivalence/id_equivalence.dart'; | 
|  | 18 import '../equivalence/id_equivalence_helper.dart'; | 
|  | 19 import 'package:kernel/ast.dart' as ir; | 
|  | 20 | 
|  | 21 main() { | 
|  | 22   asyncTest(() async { | 
|  | 23     Directory dataDir = new Directory.fromUri(Platform.script.resolve('data')); | 
|  | 24     await for (FileSystemEntity entity in dataDir.list()) { | 
|  | 25       print('Checking ${entity.uri}'); | 
|  | 26       String annotatedCode = await new File.fromUri(entity.uri).readAsString(); | 
|  | 27       await checkCode(annotatedCode, computeJumpsData, compileFromSource); | 
|  | 28       await checkCode(annotatedCode, computeKernelJumpsData, compileFromDill); | 
|  | 29     } | 
|  | 30   }); | 
|  | 31 } | 
|  | 32 | 
|  | 33 /// Compute closure data mapping for [_member] as a [MemberElement]. | 
|  | 34 /// | 
|  | 35 /// Fills [actualMap] with the data and [sourceSpanMap] with the source spans | 
|  | 36 /// for the data origin. | 
|  | 37 void computeJumpsData( | 
|  | 38     Compiler compiler, MemberEntity _member, Map<Id, ActualData> actualMap, | 
|  | 39     {bool verbose: false}) { | 
|  | 40   MemberElement member = _member; | 
|  | 41   new JumpsAstComputer(compiler.reporter, actualMap, member.resolvedAst).run(); | 
|  | 42 } | 
|  | 43 | 
|  | 44 /// Compute closure data mapping for [member] as a kernel based element. | 
|  | 45 /// | 
|  | 46 /// Fills [actualMap] with the data and [sourceSpanMap] with the source spans | 
|  | 47 /// for the data origin. | 
|  | 48 void computeKernelJumpsData( | 
|  | 49     Compiler compiler, MemberEntity member, Map<Id, ActualData> actualMap, | 
|  | 50     {bool verbose: false}) { | 
|  | 51   KernelBackendStrategy backendStrategy = compiler.backendStrategy; | 
|  | 52   KernelToElementMapForBuilding elementMap = backendStrategy.elementMap; | 
|  | 53   GlobalLocalsMap localsMap = backendStrategy.globalLocalsMapForTesting; | 
|  | 54   MemberDefinition definition = elementMap.getMemberDefinition(member); | 
|  | 55   new JumpsIrChecker( | 
|  | 56           actualMap, elementMap, member, localsMap.getLocalsMap(member)) | 
|  | 57       .run(definition.node); | 
|  | 58 } | 
|  | 59 | 
|  | 60 class TargetData { | 
|  | 61   final int index; | 
|  | 62   final NodeId id; | 
|  | 63   final SourceSpan sourceSpan; | 
|  | 64   final JumpTarget target; | 
|  | 65 | 
|  | 66   TargetData(this.index, this.id, this.sourceSpan, this.target); | 
|  | 67 } | 
|  | 68 | 
|  | 69 class GotoData { | 
|  | 70   final NodeId id; | 
|  | 71   final SourceSpan sourceSpan; | 
|  | 72   final JumpTarget target; | 
|  | 73 | 
|  | 74   GotoData(this.id, this.sourceSpan, this.target); | 
|  | 75 } | 
|  | 76 | 
|  | 77 abstract class JumpsMixin { | 
|  | 78   int index = 0; | 
|  | 79   Map<JumpTarget, TargetData> targets = <JumpTarget, TargetData>{}; | 
|  | 80   List<GotoData> gotos = <GotoData>[]; | 
|  | 81 | 
|  | 82   void registerValue(SourceSpan sourceSpan, Id id, String value, Object object); | 
|  | 83 | 
|  | 84   void processData() { | 
|  | 85     targets.forEach((JumpTarget target, TargetData data) { | 
|  | 86       StringBuffer sb = new StringBuffer(); | 
|  | 87       sb.write(data.index); | 
|  | 88       sb.write('@'); | 
|  | 89       bool needsComma = false; | 
|  | 90       if (target.isBreakTarget) { | 
|  | 91         sb.write('break'); | 
|  | 92         needsComma = true; | 
|  | 93       } | 
|  | 94       if (target.isContinueTarget) { | 
|  | 95         if (needsComma) { | 
|  | 96           sb.write(','); | 
|  | 97         } | 
|  | 98         sb.write('continue'); | 
|  | 99         needsComma = true; | 
|  | 100       } | 
|  | 101       String value = sb.toString(); | 
|  | 102       registerValue(data.sourceSpan, data.id, value, target); | 
|  | 103     }); | 
|  | 104     gotos.forEach((GotoData data) { | 
|  | 105       StringBuffer sb = new StringBuffer(); | 
|  | 106       sb.write('target='); | 
|  | 107       TargetData targetData = targets[data.target]; | 
|  | 108       sb.write(targetData.index); | 
|  | 109       String value = sb.toString(); | 
|  | 110       registerValue(data.sourceSpan, data.id, value, data); | 
|  | 111     }); | 
|  | 112   } | 
|  | 113 } | 
|  | 114 | 
|  | 115 /// Ast visitor for computing jump data. | 
|  | 116 class JumpsAstComputer extends AstDataExtractor with JumpsMixin { | 
|  | 117   JumpsAstComputer(DiagnosticReporter reporter, Map<Id, ActualData> actualMap, | 
|  | 118       ResolvedAst resolvedAst) | 
|  | 119       : super(reporter, actualMap, resolvedAst); | 
|  | 120 | 
|  | 121   void run() { | 
|  | 122     super.run(); | 
|  | 123     processData(); | 
|  | 124   } | 
|  | 125 | 
|  | 126   @override | 
|  | 127   String computeNodeValue(ast.Node node, [AstElement element]) { | 
|  | 128     // Node values are computed post-visit in [processData]. | 
|  | 129     return null; | 
|  | 130   } | 
|  | 131 | 
|  | 132   @override | 
|  | 133   String computeElementValue(AstElement element) { | 
|  | 134     return null; | 
|  | 135   } | 
|  | 136 | 
|  | 137   @override | 
|  | 138   visitLoop(ast.Loop node) { | 
|  | 139     JumpTarget target = elements.getTargetDefinition(node); | 
|  | 140     if (target != null) { | 
|  | 141       NodeId id = computeLoopNodeId(node); | 
|  | 142       SourceSpan sourceSpan = computeSourceSpan(node); | 
|  | 143       targets[target] = new TargetData(index++, id, sourceSpan, target); | 
|  | 144     } | 
|  | 145     super.visitLoop(node); | 
|  | 146   } | 
|  | 147 | 
|  | 148   @override | 
|  | 149   visitGotoStatement(ast.GotoStatement node) { | 
|  | 150     JumpTarget target = elements.getTargetOf(node); | 
|  | 151     NodeId id = computeGotoNodeId(node); | 
|  | 152     SourceSpan sourceSpan = computeSourceSpan(node); | 
|  | 153     gotos.add(new GotoData(id, sourceSpan, target)); | 
|  | 154     super.visitGotoStatement(node); | 
|  | 155   } | 
|  | 156 } | 
|  | 157 | 
|  | 158 /// Kernel IR visitor for computing jump data. | 
|  | 159 class JumpsIrChecker extends IrDataExtractor with JumpsMixin { | 
|  | 160   final KernelToLocalsMap _localsMap; | 
|  | 161 | 
|  | 162   JumpsIrChecker(Map<Id, ActualData> actualMap, KernelToElementMap elementMap, | 
|  | 163       MemberEntity member, this._localsMap) | 
|  | 164       : super(actualMap); | 
|  | 165 | 
|  | 166   void run(ir.Node root) { | 
|  | 167     super.run(root); | 
|  | 168     processData(); | 
|  | 169   } | 
|  | 170 | 
|  | 171   @override | 
|  | 172   String computeNodeValue(ir.Node node) { | 
|  | 173     // Node values are computed post-visit in [processData]. | 
|  | 174     return null; | 
|  | 175   } | 
|  | 176 | 
|  | 177   @override | 
|  | 178   String computeMemberValue(ir.Member member) { | 
|  | 179     return null; | 
|  | 180   } | 
|  | 181 | 
|  | 182   visitForStatement(ir.ForStatement node) { | 
|  | 183     JumpTarget target = _localsMap.getJumpTargetForFor(node); | 
|  | 184     if (target != null) { | 
|  | 185       NodeId id = computeLoopNodeId(node); | 
|  | 186       SourceSpan sourceSpan = computeSourceSpan(node); | 
|  | 187       targets[target] = new TargetData(index++, id, sourceSpan, target); | 
|  | 188     } | 
|  | 189     super.visitForStatement(node); | 
|  | 190   } | 
|  | 191 | 
|  | 192   // TODO(johnniwinther): Support testing of do, for-in and while loops. | 
|  | 193 | 
|  | 194   visitBreakStatement(ir.BreakStatement node) { | 
|  | 195     JumpTarget target = _localsMap.getJumpTargetForBreak(node); | 
|  | 196     assert(target != null, 'No target for $node.'); | 
|  | 197     NodeId id = computeGotoNodeId(node); | 
|  | 198     SourceSpan sourceSpan = computeSourceSpan(node); | 
|  | 199     gotos.add(new GotoData(id, sourceSpan, target)); | 
|  | 200     super.visitBreakStatement(node); | 
|  | 201   } | 
|  | 202 } | 
| OLD | NEW | 
|---|