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

Side by Side Diff: pkg/compiler/lib/src/cps_ir/cps_ir_integrity.dart

Issue 1251083002: dart2js cps: Avoid deep recursion using trampolines and basic blocks. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Rebase Created 5 years, 5 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 unified diff | Download patch
« no previous file with comments | « no previous file | pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 library dart2js.cps_ir_integrity; 1 library dart2js.cps_ir_integrity;
2 2
3 import 'cps_ir_nodes.dart'; 3 import 'cps_ir_nodes.dart';
4 import 'cps_ir_nodes_sexpr.dart'; 4 import 'cps_ir_nodes_sexpr.dart';
5 import '../tracer.dart' as tracer; 5 import '../tracer.dart' as tracer;
6 6
7 /// Dump S-expressions on error if the tracer is enabled. 7 /// Dump S-expressions on error if the tracer is enabled.
8 /// 8 ///
9 /// Technically this has nothing to do with the tracer, but if you want one 9 /// Technically this has nothing to do with the tracer, but if you want one
10 /// enabled, you typically want the other as well, so we use the same flag. 10 /// enabled, you typically want the other as well, so we use the same flag.
(...skipping 14 matching lines...) Expand all
25 /// - Each reference object occurs only once in the IR (no sharing). 25 /// - Each reference object occurs only once in the IR (no sharing).
26 /// 26 ///
27 class CheckCpsIntegrity extends RecursiveVisitor { 27 class CheckCpsIntegrity extends RecursiveVisitor {
28 28
29 FunctionDefinition topLevelNode; 29 FunctionDefinition topLevelNode;
30 30
31 Set<Definition> seenDefinitions = new Set<Definition>(); 31 Set<Definition> seenDefinitions = new Set<Definition>();
32 Map<Definition, Set<Reference>> seenReferences = 32 Map<Definition, Set<Reference>> seenReferences =
33 <Definition, Set<Reference>>{}; 33 <Definition, Set<Reference>>{};
34 34
35 Map<Definition, Node> bindings = <Definition, Node>{}; 35 Set<Definition> inScope = new Set<Definition>();
36 Set<Continuation> insideContinuations = new Set<Continuation>(); 36 Set<Continuation> insideContinuations = new Set<Continuation>();
37 37
38 doInScope(Iterable<Definition> defs, Node binding, action()) {
39 for (Definition def in defs) {
40 bindings[def] = binding;
41 }
42 action();
43 for (Definition def in defs) {
44 bindings.remove(def);
45 }
46 }
47
48 void markAsSeen(Definition def) { 38 void markAsSeen(Definition def) {
49 if (!seenDefinitions.add(def)) { 39 if (!seenDefinitions.add(def)) {
50 error('Redeclared $def', def); 40 error('Redeclared $def', def);
51 } 41 }
52 seenReferences[def] = new Set<Reference>(); 42 seenReferences[def] = new Set<Reference>();
53 } 43 }
54 44
55 @override 45 void enterScope(Iterable<Definition> definitions) {
56 visitLetCont(LetCont node) { 46 inScope.addAll(definitions);
57 // Analyze each continuation separately without the others in scope. 47 pushAction(() => inScope.removeAll(definitions));
58 for (Continuation continuation in node.continuations) { 48 }
59 // We always consider a continuation to be in scope of itself. 49
60 // The isRecursive flag is checked explicitly to give more useful 50 void enterContinuation(Continuation cont) {
61 // error messages. 51 insideContinuations.add(cont);
62 doInScope([continuation], node, () => visit(continuation)); 52 pushAction(() => insideContinuations.remove(cont));
63 } 53 }
64 // Analyze the body with all continuations in scope. 54
65 doInScope(node.continuations, node, () => visit(node.body)); 55 void check(FunctionDefinition node) {
56 topLevelNode = node;
57 visit(node);
58 // Check for broken reference chains. We check this last, so out-of-scope
59 // references are not classified as a broken reference chain.
60 seenDefinitions.forEach(checkReferenceChain);
66 } 61 }
67 62
68 @override 63 @override
69 visitContinuation(Continuation node) { 64 Expression traverseLetCont(LetCont node) {
70 markAsSeen(node); 65 node.continuations.forEach(markAsSeen);
71 if (node.isReturnContinuation) { 66 node.continuations.forEach(push);
72 error('Non-return continuation missing body', node); 67
73 } 68 // Put all continuations in scope when visiting the body.
74 node.parameters.forEach(markAsSeen); 69 enterScope(node.continuations);
75 insideContinuations.add(node); 70
76 doInScope(node.parameters, node, () => visit(node.body)); 71 return node.body;
77 insideContinuations.remove(node);
78 } 72 }
79 73
80 @override 74 @override
81 visitLetPrim(LetPrim node) { 75 Expression traverseLetPrim(LetPrim node) {
82 markAsSeen(node.primitive); 76 markAsSeen(node.primitive);
77
78 // Process references in the primitive.
83 visit(node.primitive); 79 visit(node.primitive);
84 doInScope([node.primitive], node, () => visit(node.body)); 80
81 // Put the primitive in scope when visiting the body.
82 enterScope([node.primitive]);
83
84 return node.body;
85 } 85 }
86 86
87 @override 87 @override
88 visitLetMutable(LetMutable node) { 88 Expression traverseLetMutable(LetMutable node) {
89 markAsSeen(node.variable); 89 markAsSeen(node.variable);
90 processReference(node.value); 90 processReference(node.value);
91 doInScope([node.variable], node, () => visit(node.body)); 91
92 // Put the primitive in scope when visiting the body.
93 enterScope([node.variable]);
94
95 return node.body;
96 }
97
98 @override
99 Expression traverseContinuation(Continuation cont) {
100 if (cont.isReturnContinuation) {
101 error('Non-return continuation missing body', cont);
102 }
103 cont.parameters.forEach(markAsSeen);
104 enterScope(cont.parameters);
105 // Put every continuation in scope at its own body. The isRecursive
106 // flag is checked explicitly using [insideContinuations].
107 enterScope([cont]);
108 enterContinuation(cont);
109 return cont.body;
92 } 110 }
93 111
94 @override 112 @override
95 visitFunctionDefinition(FunctionDefinition node) { 113 visitFunctionDefinition(FunctionDefinition node) {
96 if (node.thisParameter != null) { 114 if (node.thisParameter != null) {
97 markAsSeen(node.thisParameter); 115 markAsSeen(node.thisParameter);
116 enterScope([node.thisParameter]);
98 } 117 }
99 node.parameters.forEach(markAsSeen); 118 node.parameters.forEach(markAsSeen);
119 enterScope(node.parameters);
100 markAsSeen(node.returnContinuation); 120 markAsSeen(node.returnContinuation);
121 enterScope([node.returnContinuation]);
101 if (!node.returnContinuation.isReturnContinuation) { 122 if (!node.returnContinuation.isReturnContinuation) {
102 error('Return continuation with a body', node); 123 error('Return continuation with a body', node);
103 } 124 }
104 doInOptionalScope(node.thisParameter, node, 125 visit(node.body);
105 () => doInScope(node.parameters, node,
106 () => doInScope([node.returnContinuation], node,
107 () => visit(node.body))));
108 }
109
110 doInOptionalScope(Parameter parameter, Node node, action) {
111 return (parameter == null)
112 ? action()
113 : doInScope([parameter], node, action);
114 } 126 }
115 127
116 @override 128 @override
117 processReference(Reference reference) { 129 processReference(Reference reference) {
118 if (!bindings.containsKey(reference.definition)) { 130 if (!inScope.contains(reference.definition)) {
119 error('Referenced out of scope: ${reference.definition}', reference); 131 error('Referenced out of scope: ${reference.definition}', reference);
120 } 132 }
121 if (!seenReferences[reference.definition].add(reference)) { 133 if (!seenReferences[reference.definition].add(reference)) {
122 error('Duplicate use of Reference to ${reference.definition}', reference); 134 error('Duplicate use of Reference to ${reference.definition}', reference);
123 } 135 }
124 } 136 }
125 137
126 @override 138 @override
127 processInvokeContinuation(InvokeContinuation node) { 139 processInvokeContinuation(InvokeContinuation node) {
128 Continuation target = node.continuation.definition; 140 Continuation target = node.continuation.definition;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 } 186 }
175 } else { 187 } else {
176 sexpr = '(Set DUMP_IR flag to enable)'; 188 sexpr = '(Set DUMP_IR flag to enable)';
177 } 189 }
178 throw 'CPS integrity violation in ${topLevelNode.element}:\n' 190 throw 'CPS integrity violation in ${topLevelNode.element}:\n'
179 '$message\n\n' 191 '$message\n\n'
180 'SExpr dump (offending node marked with **):\n\n' 192 'SExpr dump (offending node marked with **):\n\n'
181 '$sexpr\n'; 193 '$sexpr\n';
182 } 194 }
183 195
184 void check(FunctionDefinition node) {
185 topLevelNode = node;
186 visit(node);
187
188 // Check this last, so out-of-scope references are not classified as
189 // a broken reference chain.
190 seenDefinitions.forEach(checkReferenceChain);
191 }
192
193 } 196 }
OLDNEW
« no previous file with comments | « no previous file | pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698