FIR CFG: remove ordering from control flow through in-place lambdas

Old graph:

  arg -> lambda enter -> ... -> lambda exit -> lambda enter -> ... ->
   -> lambda exit -> call

New graph:

  arg -+-> lambda enter -> ... -> lambda exit -+-> call
       \-> lambda enter -> ... -> lambda exit -/
This commit is contained in:
pyos
2022-11-23 10:10:16 +01:00
committed by teamcity
parent 5dce772f0b
commit c4c05f5248
41 changed files with 515 additions and 555 deletions
@@ -71,8 +71,8 @@ digraph defaultArguments_kt {
14 -> {15};
16 -> {17};
16 -> {16} [style=dashed];
17 -> {21};
17 -> {18} [color=red];
17 -> {21 19};
17 -> {18} [style=dotted];
17 -> {21} [style=dashed];
18 -> {19};
19 -> {20};
@@ -80,7 +80,6 @@ digraph defaultArguments_kt {
22 -> {23};
23 -> {24};
24 -> {25};
25 -> {19} [color=red];
25 -> {18} [color=green];
25 -> {18};
}
@@ -209,8 +209,8 @@ digraph flowFromInplaceLambda_kt {
}
60 -> {61};
61 -> {62};
62 -> {70};
62 -> {63} [color=red];
62 -> {70 64};
62 -> {63} [style=dotted];
62 -> {70} [style=dashed];
63 -> {64};
64 -> {65};
@@ -223,8 +223,7 @@ digraph flowFromInplaceLambda_kt {
72 -> {73};
73 -> {74};
74 -> {75};
75 -> {64} [color=red];
75 -> {63} [color=green];
75 -> {63};
subgraph cluster_20 {
color=red
@@ -286,18 +285,20 @@ digraph flowFromInplaceLambda_kt {
}
76 -> {77};
77 -> {78};
78 -> {97};
78 -> {79} [color=red];
78 -> {97 80};
78 -> {79} [style=dotted];
78 -> {97} [style=dashed];
79 -> {80};
79 -> {81} [color=red];
79 -> {80} [color=green];
80 -> {81};
81 -> {82};
82 -> {83};
83 -> {84};
84 -> {105};
84 -> {85} [color=red];
84 -> {105 86};
84 -> {85} [style=dotted];
84 -> {105} [style=dashed];
85 -> {86};
85 -> {87} [color=red];
85 -> {86} [color=green];
86 -> {87};
87 -> {88};
88 -> {89};
@@ -315,8 +316,7 @@ digraph flowFromInplaceLambda_kt {
101 -> {102};
102 -> {103};
103 -> {104};
104 -> {81} [color=red];
104 -> {79} [color=green];
104 -> {79};
105 -> {106};
106 -> {107};
107 -> {108};
@@ -327,8 +327,7 @@ digraph flowFromInplaceLambda_kt {
112 -> {113};
113 -> {114};
114 -> {115};
115 -> {87} [color=red];
115 -> {85} [color=green];
115 -> {85};
subgraph cluster_26 {
color=red
@@ -390,19 +389,21 @@ digraph flowFromInplaceLambda_kt {
}
116 -> {117};
117 -> {118};
118 -> {137};
118 -> {119} [color=red];
118 -> {137 120};
118 -> {119} [style=dotted];
118 -> {137} [style=dashed];
119 -> {120};
119 -> {121} [color=red];
119 -> {120} [color=green];
119 -> {118} [color=green style=dashed];
120 -> {121};
121 -> {122};
122 -> {123};
123 -> {124};
124 -> {145};
124 -> {125} [color=red];
124 -> {145 126};
124 -> {125} [style=dotted];
124 -> {145} [style=dashed];
125 -> {126};
125 -> {127} [color=red];
125 -> {126} [color=green];
125 -> {124} [color=green style=dashed];
126 -> {127};
127 -> {128};
@@ -421,8 +422,7 @@ digraph flowFromInplaceLambda_kt {
141 -> {142};
142 -> {143};
143 -> {144};
144 -> {121} [color=red];
144 -> {119} [color=green];
144 -> {119};
145 -> {146};
146 -> {147};
147 -> {148};
@@ -433,8 +433,7 @@ digraph flowFromInplaceLambda_kt {
152 -> {153};
153 -> {154};
154 -> {155};
155 -> {127} [color=red];
155 -> {125} [color=green];
155 -> {125};
subgraph cluster_32 {
color=red
@@ -494,16 +493,18 @@ digraph flowFromInplaceLambda_kt {
}
156 -> {157};
157 -> {158};
158 -> {159 176};
158 -> {159 176 160};
158 -> {176} [style=dashed];
159 -> {160};
159 -> {161} [color=red];
159 -> {160} [color=green];
160 -> {161};
161 -> {162};
162 -> {163};
163 -> {164};
164 -> {165 184};
164 -> {165 184 166};
164 -> {184} [style=dashed];
165 -> {166};
165 -> {167} [color=red];
165 -> {166} [color=green];
166 -> {167};
167 -> {168};
168 -> {169};
@@ -590,17 +591,19 @@ digraph flowFromInplaceLambda_kt {
}
194 -> {195};
195 -> {196};
196 -> {197 214};
196 -> {197 214 198};
196 -> {214} [style=dashed];
197 -> {198};
197 -> {199} [color=red];
197 -> {198} [color=green];
197 -> {196} [color=green style=dashed];
198 -> {199};
199 -> {200};
200 -> {201};
201 -> {202};
202 -> {203 222};
202 -> {203 222 204};
202 -> {222} [style=dashed];
203 -> {204};
203 -> {205} [color=red];
203 -> {204} [color=green];
203 -> {202} [color=green style=dashed];
204 -> {205};
205 -> {206};
@@ -688,16 +691,18 @@ digraph flowFromInplaceLambda_kt {
}
232 -> {233};
233 -> {234};
234 -> {235 252};
234 -> {235 252 236};
234 -> {252} [style=dashed];
235 -> {236};
235 -> {237} [color=red];
235 -> {236} [color=green];
236 -> {237};
237 -> {238};
238 -> {239};
239 -> {240};
240 -> {241 260};
240 -> {241 260 242};
240 -> {260} [style=dashed];
241 -> {242};
241 -> {243} [color=red];
241 -> {242} [color=green];
242 -> {243};
243 -> {244};
244 -> {245};
@@ -787,16 +792,18 @@ digraph flowFromInplaceLambda_kt {
}
270 -> {271};
271 -> {272};
272 -> {289};
272 -> {273} [color=red];
272 -> {289 274};
272 -> {273} [style=dotted];
272 -> {289} [style=dashed];
273 -> {274};
273 -> {279} [color=red];
273 -> {274} [color=green];
274 -> {275};
275 -> {276};
276 -> {301};
276 -> {277} [color=red];
276 -> {301 278};
276 -> {277} [style=dotted];
276 -> {301} [style=dashed];
277 -> {278};
277 -> {279} [color=red];
277 -> {278} [color=green];
278 -> {279};
279 -> {280};
280 -> {281};
@@ -818,8 +825,7 @@ digraph flowFromInplaceLambda_kt {
297 -> {298};
298 -> {299};
299 -> {300};
300 -> {279} [color=red];
300 -> {273} [color=green];
300 -> {273};
301 -> {302};
302 -> {303};
303 -> {304};
@@ -831,8 +837,7 @@ digraph flowFromInplaceLambda_kt {
309 -> {310};
310 -> {311};
311 -> {312};
312 -> {279} [color=red];
312 -> {277} [color=green];
312 -> {277};
subgraph cluster_56 {
color=red
@@ -897,17 +902,19 @@ digraph flowFromInplaceLambda_kt {
}
313 -> {314};
314 -> {315};
315 -> {332};
315 -> {316} [color=red];
315 -> {332 317};
315 -> {316} [style=dotted];
315 -> {332} [style=dashed];
316 -> {317};
316 -> {322} [color=red];
316 -> {317} [color=green];
316 -> {315} [color=green style=dashed];
317 -> {318};
318 -> {319};
319 -> {344};
319 -> {320} [color=red];
319 -> {344 321};
319 -> {320} [style=dotted];
319 -> {344} [style=dashed];
320 -> {321};
320 -> {322} [color=red];
320 -> {321} [color=green];
320 -> {319} [color=green style=dashed];
321 -> {322};
322 -> {323};
@@ -930,8 +937,7 @@ digraph flowFromInplaceLambda_kt {
340 -> {341};
341 -> {342};
342 -> {343};
343 -> {322} [color=red];
343 -> {316} [color=green];
343 -> {316};
344 -> {345};
345 -> {346};
346 -> {347};
@@ -943,8 +949,7 @@ digraph flowFromInplaceLambda_kt {
352 -> {353};
353 -> {354};
354 -> {355};
355 -> {322} [color=red];
355 -> {320} [color=green];
355 -> {320};
subgraph cluster_62 {
color=red
@@ -1007,14 +1012,16 @@ digraph flowFromInplaceLambda_kt {
}
356 -> {357};
357 -> {358};
358 -> {359 373};
358 -> {359 373 360};
358 -> {373} [style=dashed];
359 -> {360};
359 -> {365} [color=red];
359 -> {360} [color=green];
360 -> {361};
361 -> {362};
362 -> {363 385};
362 -> {363 385 364};
362 -> {385} [style=dashed];
363 -> {364};
363 -> {365} [color=red];
363 -> {364} [color=green];
364 -> {365};
365 -> {366};
366 -> {367};
@@ -1109,15 +1116,17 @@ digraph flowFromInplaceLambda_kt {
}
397 -> {398};
398 -> {399};
399 -> {400 414};
399 -> {400 414 401};
399 -> {414} [style=dashed];
400 -> {401};
400 -> {406} [color=red];
400 -> {401} [color=green];
400 -> {399} [color=green style=dashed];
401 -> {402};
402 -> {403};
403 -> {404 426};
403 -> {404 426 405};
403 -> {426} [style=dashed];
404 -> {405};
404 -> {406} [color=red];
404 -> {405} [color=green];
404 -> {403} [color=green style=dashed];
405 -> {406};
406 -> {407};
@@ -1213,14 +1222,16 @@ digraph flowFromInplaceLambda_kt {
}
438 -> {439};
439 -> {440};
440 -> {441 455};
440 -> {441 455 442};
440 -> {455} [style=dashed];
441 -> {442};
441 -> {447} [color=red];
441 -> {442} [color=green];
442 -> {443};
443 -> {444};
444 -> {445 467};
444 -> {445 467 446};
444 -> {467} [style=dashed];
445 -> {446};
445 -> {447} [color=red];
445 -> {446} [color=green];
446 -> {447};
447 -> {448};
448 -> {449};
@@ -1296,15 +1307,17 @@ digraph flowFromInplaceLambda_kt {
}
479 -> {480};
480 -> {481};
481 -> {493};
481 -> {482} [color=red];
481 -> {493 483};
481 -> {482} [style=dotted];
481 -> {493} [style=dashed];
482 -> {483};
482 -> {487} [color=red];
482 -> {483} [color=green];
483 -> {484};
484 -> {498};
484 -> {485} [color=red];
484 -> {498 486};
484 -> {485} [style=dotted];
484 -> {498} [style=dashed];
485 -> {486};
485 -> {487} [color=red];
485 -> {486} [color=green];
486 -> {487};
487 -> {488};
488 -> {489};
@@ -1315,14 +1328,12 @@ digraph flowFromInplaceLambda_kt {
494 -> {495};
495 -> {496};
496 -> {497};
497 -> {487} [color=red];
497 -> {482} [color=green];
497 -> {482};
498 -> {499};
499 -> {500};
500 -> {501};
501 -> {502};
502 -> {487} [color=red];
502 -> {485} [color=green];
502 -> {485};
subgraph cluster_86 {
color=red
@@ -1367,9 +1378,10 @@ digraph flowFromInplaceLambda_kt {
}
503 -> {504};
504 -> {505};
505 -> {506 514};
505 -> {506 514 507};
505 -> {514} [style=dashed];
506 -> {507};
506 -> {508} [color=red];
506 -> {507} [color=green];
507 -> {508};
508 -> {509};
509 -> {510};
@@ -1378,16 +1390,17 @@ digraph flowFromInplaceLambda_kt {
512 -> {513};
514 -> {515};
515 -> {516};
516 -> {521};
516 -> {517} [color=red];
516 -> {521 518};
516 -> {517} [style=dotted];
516 -> {521} [style=dashed];
517 -> {518};
517 -> {508} [color=red];
517 -> {518} [color=green];
518 -> {519};
519 -> {520};
521 -> {522};
522 -> {523};
523 -> {524};
524 -> {525};
525 -> {517} [color=green];
525 -> {517};
}
@@ -130,17 +130,19 @@ digraph flowFromInplaceLambda2_kt {
}
25 -> {26};
26 -> {27};
27 -> {41};
27 -> {28} [color=red];
27 -> {41 29};
27 -> {28} [style=dotted];
27 -> {41} [style=dashed];
28 -> {29};
28 -> {35} [color=red];
28 -> {29} [color=green];
29 -> {30};
30 -> {31};
31 -> {32};
32 -> {48};
32 -> {33} [color=red];
32 -> {48 34};
32 -> {33} [style=dotted];
32 -> {48} [style=dashed];
33 -> {34};
33 -> {35} [color=red];
33 -> {34} [color=green];
34 -> {35};
35 -> {36};
36 -> {37};
@@ -153,16 +155,14 @@ digraph flowFromInplaceLambda2_kt {
44 -> {45};
45 -> {46};
46 -> {47};
47 -> {35} [color=red];
47 -> {28} [color=green];
47 -> {28};
48 -> {49};
49 -> {50};
50 -> {51};
51 -> {52};
52 -> {53};
53 -> {54};
54 -> {35} [color=red];
54 -> {33} [color=green];
54 -> {33};
subgraph cluster_14 {
color=red
@@ -215,18 +215,20 @@ digraph flowFromInplaceLambda2_kt {
}
55 -> {56};
56 -> {57};
57 -> {72};
57 -> {58} [color=red];
57 -> {72 59};
57 -> {58} [style=dotted];
57 -> {72} [style=dashed];
58 -> {59};
58 -> {66} [color=red];
58 -> {59} [color=green];
59 -> {60};
60 -> {61};
61 -> {62};
62 -> {63};
63 -> {79};
63 -> {64} [color=red];
63 -> {79 65};
63 -> {64} [style=dotted];
63 -> {79} [style=dashed];
64 -> {65};
64 -> {66} [color=red];
64 -> {65} [color=green];
65 -> {66};
66 -> {67};
67 -> {68};
@@ -239,16 +241,14 @@ digraph flowFromInplaceLambda2_kt {
75 -> {76};
76 -> {77};
77 -> {78};
78 -> {66} [color=red];
78 -> {58} [color=green];
78 -> {58};
79 -> {80};
80 -> {81};
81 -> {82};
82 -> {83};
83 -> {84};
84 -> {85};
85 -> {66} [color=red];
85 -> {64} [color=green];
85 -> {64};
subgraph cluster_20 {
color=red
@@ -331,10 +331,11 @@ digraph flowFromInplaceLambda2_kt {
}
86 -> {87};
87 -> {88};
88 -> {118};
88 -> {89} [color=red];
88 -> {118 90};
88 -> {89} [style=dotted];
88 -> {118} [style=dashed];
89 -> {90};
89 -> {112} [color=red];
89 -> {90} [color=green];
90 -> {91};
91 -> {92};
92 -> {93};
@@ -354,10 +355,11 @@ digraph flowFromInplaceLambda2_kt {
106 -> {107};
107 -> {108};
108 -> {109};
109 -> {125};
109 -> {110} [color=red];
109 -> {125 111};
109 -> {110} [style=dotted];
109 -> {125} [style=dashed];
110 -> {111};
110 -> {112} [color=red];
110 -> {111} [color=green];
111 -> {112};
112 -> {113};
113 -> {114};
@@ -370,16 +372,14 @@ digraph flowFromInplaceLambda2_kt {
121 -> {122};
122 -> {123};
123 -> {124};
124 -> {112} [color=red];
124 -> {89} [color=green];
124 -> {89};
125 -> {126};
126 -> {127};
127 -> {128};
128 -> {129};
129 -> {130};
130 -> {131};
131 -> {112} [color=red];
131 -> {110} [color=green];
131 -> {110};
subgraph cluster_31 {
color=red
@@ -518,29 +518,32 @@ digraph flowFromInplaceLambda2_kt {
150 -> {151};
151 -> {152};
152 -> {153};
153 -> {187};
153 -> {154} [color=red];
153 -> {187 155};
153 -> {154} [style=dotted];
153 -> {187} [style=dashed];
154 -> {155};
154 -> {171} [color=red];
154 -> {155} [color=green];
155 -> {156};
156 -> {157};
157 -> {165};
158 -> {159};
159 -> {160};
160 -> {180};
160 -> {161} [color=red];
160 -> {180 162};
160 -> {161} [style=dotted];
160 -> {180} [style=dashed];
161 -> {162};
161 -> {171} [color=red];
161 -> {162} [color=green];
162 -> {163};
163 -> {164};
164 -> {165};
165 -> {171 166};
166 -> {167};
167 -> {168};
168 -> {192};
168 -> {169} [color=red];
168 -> {192 170};
168 -> {169} [style=dotted];
168 -> {192} [style=dashed];
169 -> {170};
169 -> {172} [color=red];
169 -> {170} [color=green];
170 -> {172};
171 -> {172} [color=red];
172 -> {173};
@@ -556,14 +559,12 @@ digraph flowFromInplaceLambda2_kt {
183 -> {184};
184 -> {185};
185 -> {186};
186 -> {171} [color=red];
186 -> {161} [color=green];
186 -> {161};
187 -> {188};
188 -> {189};
189 -> {190};
190 -> {191};
191 -> {171} [color=red];
191 -> {154} [color=green];
191 -> {154};
192 -> {193};
193 -> {194};
194 -> {195};
@@ -571,8 +572,7 @@ digraph flowFromInplaceLambda2_kt {
196 -> {197};
197 -> {198};
198 -> {199};
199 -> {172} [color=red];
199 -> {169} [color=green];
199 -> {169};
subgraph cluster_47 {
color=red
@@ -626,17 +626,19 @@ digraph flowFromInplaceLambda2_kt {
201 -> {202};
202 -> {203 207};
203 -> {204};
204 -> {218};
204 -> {205} [color=red];
204 -> {218 206};
204 -> {205} [style=dotted];
204 -> {218} [style=dashed];
205 -> {206};
205 -> {212} [color=red];
205 -> {206} [color=green];
206 -> {207};
207 -> {212 208};
208 -> {209};
209 -> {225};
209 -> {210} [color=red];
209 -> {225 211};
209 -> {210} [style=dotted];
209 -> {225} [style=dashed];
210 -> {211};
210 -> {213} [color=red];
210 -> {211} [color=green];
211 -> {213};
212 -> {213} [color=red];
213 -> {214};
@@ -649,14 +651,12 @@ digraph flowFromInplaceLambda2_kt {
221 -> {222};
222 -> {223};
223 -> {224};
224 -> {212} [color=red];
224 -> {205} [color=green];
224 -> {205};
225 -> {226};
226 -> {227};
227 -> {228};
228 -> {229};
229 -> {213} [color=red];
229 -> {210} [color=green];
229 -> {210};
subgraph cluster_53 {
color=red
@@ -762,29 +762,32 @@ digraph flowFromInplaceLambda2_kt {
237 -> {238};
238 -> {239};
239 -> {240};
240 -> {271};
240 -> {241} [color=red];
240 -> {271 242};
240 -> {241} [style=dotted];
240 -> {271} [style=dashed];
241 -> {242};
241 -> {258} [color=red];
241 -> {242} [color=green];
242 -> {243};
243 -> {244};
244 -> {252};
245 -> {246};
246 -> {247};
247 -> {264};
247 -> {248} [color=red];
247 -> {264 249};
247 -> {248} [style=dotted];
247 -> {264} [style=dashed];
248 -> {249};
248 -> {258} [color=red];
248 -> {249} [color=green];
249 -> {250};
250 -> {251};
251 -> {252};
252 -> {258 253};
253 -> {254};
254 -> {255};
255 -> {278};
255 -> {256} [color=red];
255 -> {278 257};
255 -> {256} [style=dotted];
255 -> {278} [style=dashed];
256 -> {257};
256 -> {259} [color=red];
256 -> {257} [color=green];
257 -> {259};
258 -> {259} [color=red];
259 -> {260};
@@ -797,24 +800,21 @@ digraph flowFromInplaceLambda2_kt {
267 -> {268};
268 -> {269};
269 -> {270};
270 -> {258} [color=red];
270 -> {248} [color=green];
270 -> {248};
271 -> {272};
272 -> {273};
273 -> {274};
274 -> {275};
275 -> {276};
276 -> {277};
277 -> {258} [color=red];
277 -> {241} [color=green];
277 -> {241};
278 -> {279};
279 -> {280};
280 -> {281};
281 -> {282};
282 -> {283};
283 -> {284};
284 -> {259} [color=red];
284 -> {256} [color=green];
284 -> {256};
subgraph cluster_66 {
color=red
@@ -901,17 +901,19 @@ digraph flowFromInplaceLambda2_kt {
295 -> {312};
296 -> {297};
297 -> {298};
298 -> {315};
298 -> {299} [color=red];
298 -> {315 300};
298 -> {299} [style=dotted];
298 -> {315} [style=dashed];
299 -> {300};
299 -> {306} [color=red];
299 -> {300} [color=green];
300 -> {301};
301 -> {302};
302 -> {303};
303 -> {322};
303 -> {304} [color=red];
303 -> {322 305};
303 -> {304} [style=dotted];
303 -> {322} [style=dashed];
304 -> {305};
304 -> {306} [color=red];
304 -> {305} [color=green];
305 -> {306};
306 -> {307};
307 -> {308};
@@ -927,8 +929,7 @@ digraph flowFromInplaceLambda2_kt {
318 -> {319};
319 -> {320};
320 -> {321};
321 -> {306} [color=red];
321 -> {299} [color=green];
321 -> {299};
322 -> {323};
323 -> {324};
324 -> {325};
@@ -936,7 +937,6 @@ digraph flowFromInplaceLambda2_kt {
326 -> {327};
327 -> {328};
328 -> {329};
329 -> {306} [color=red];
329 -> {304} [color=green];
329 -> {304};
}
@@ -110,7 +110,7 @@ digraph flowFromInplaceLambda3_kt {
24 -> {25};
25 -> {26};
26 -> {27};
27 -> {28 38};
27 -> {28 38 29};
27 -> {38} [style=dashed];
28 -> {29};
28 -> {27} [color=green style=dashed];
@@ -171,7 +171,7 @@ digraph flowFromInplaceLambda3_kt {
49 -> {50};
50 -> {51};
51 -> {52};
52 -> {53 60};
52 -> {53 60 54};
52 -> {60} [style=dashed];
53 -> {54};
53 -> {52} [color=green style=dashed];
@@ -232,8 +232,8 @@ digraph flowFromInplaceLambda3_kt {
71 -> {72};
72 -> {73};
73 -> {74};
74 -> {85};
74 -> {75} [color=red];
74 -> {85 76};
74 -> {75} [style=dotted];
74 -> {85} [style=dashed];
75 -> {76};
75 -> {74} [color=green style=dashed];
@@ -250,8 +250,7 @@ digraph flowFromInplaceLambda3_kt {
87 -> {88};
88 -> {89};
89 -> {90};
90 -> {76} [color=red];
90 -> {75} [color=green];
90 -> {75};
subgraph cluster_20 {
color=red
@@ -298,8 +297,8 @@ digraph flowFromInplaceLambda3_kt {
96 -> {97};
97 -> {98};
98 -> {99};
99 -> {110};
99 -> {100} [color=red];
99 -> {110 101};
99 -> {100} [style=dotted];
99 -> {110} [style=dashed];
100 -> {101};
101 -> {102};
@@ -315,8 +314,7 @@ digraph flowFromInplaceLambda3_kt {
112 -> {113};
113 -> {114};
114 -> {115};
115 -> {101} [color=red];
115 -> {100} [color=green];
115 -> {100};
subgraph cluster_24 {
color=red
@@ -363,7 +361,7 @@ digraph flowFromInplaceLambda3_kt {
121 -> {122};
122 -> {123};
123 -> {124};
124 -> {125 135};
124 -> {125 135 126};
124 -> {135} [style=dashed];
125 -> {126};
126 -> {127};
@@ -80,7 +80,6 @@ digraph flowFromTwoInplaceLambdas_kt {
}
45 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
27 [label="Postponed exit from lambda"];
28 [label="Postponed enter to lambda"];
subgraph cluster_11 {
color=blue
@@ -97,6 +96,7 @@ digraph flowFromTwoInplaceLambdas_kt {
53 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
29 [label="Postponed exit from lambda"];
27 [label="Postponed exit from lambda"];
30 [label="Function call: R|/run2|<R|kotlin/Int?|>(...)" style="filled" fillcolor=yellow];
31 [label="Access variable R|<local>/p|"];
32 [label="Smart cast: R|<local>/p|"];
@@ -123,12 +123,12 @@ digraph flowFromTwoInplaceLambdas_kt {
23 -> {36};
24 -> {25};
25 -> {26};
26 -> {39};
26 -> {27} [color=red];
26 -> {28 39};
26 -> {27} [style=dotted];
26 -> {39} [style=dashed];
27 -> {28};
28 -> {46};
28 -> {29} [color=red];
27 -> {30};
28 -> {46 30};
28 -> {29} [style=dotted];
28 -> {46} [style=dashed];
29 -> {30};
30 -> {31};
@@ -145,8 +145,7 @@ digraph flowFromTwoInplaceLambdas_kt {
42 -> {43};
43 -> {44};
44 -> {45};
45 -> {30} [color=red];
45 -> {27} [color=green];
45 -> {27};
46 -> {47};
47 -> {48};
48 -> {49};
@@ -154,8 +153,7 @@ digraph flowFromTwoInplaceLambdas_kt {
50 -> {51};
51 -> {52};
52 -> {53};
53 -> {30} [color=red];
53 -> {29} [color=green];
53 -> {29};
subgraph cluster_13 {
color=red
@@ -196,7 +194,6 @@ digraph flowFromTwoInplaceLambdas_kt {
}
94 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
68 [label="Postponed exit from lambda"];
69 [label="Postponed enter to lambda"];
subgraph cluster_20 {
color=blue
@@ -212,6 +209,7 @@ digraph flowFromTwoInplaceLambdas_kt {
86 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
70 [label="Postponed exit from lambda"];
68 [label="Postponed exit from lambda"];
71 [label="Function call: R|/run2|<R|kotlin/Int?|>(...)" style="filled" fillcolor=yellow];
72 [label="Access variable R|<local>/p|"];
73 [label="Smart cast: R|<local>/p|"];
@@ -238,12 +236,12 @@ digraph flowFromTwoInplaceLambdas_kt {
64 -> {77};
65 -> {66};
66 -> {67};
67 -> {87};
67 -> {68} [color=red];
67 -> {69 87};
67 -> {68} [style=dotted];
67 -> {87} [style=dashed];
68 -> {69};
69 -> {80};
69 -> {70} [color=red];
68 -> {71};
69 -> {80 71};
69 -> {70} [style=dotted];
69 -> {80} [style=dashed];
70 -> {71};
71 -> {72};
@@ -260,8 +258,7 @@ digraph flowFromTwoInplaceLambdas_kt {
83 -> {84};
84 -> {85};
85 -> {86};
86 -> {71} [color=red];
86 -> {70} [color=green];
86 -> {70};
87 -> {88};
88 -> {89};
89 -> {90};
@@ -269,8 +266,7 @@ digraph flowFromTwoInplaceLambdas_kt {
91 -> {92};
92 -> {93};
93 -> {94};
94 -> {71} [color=red];
94 -> {68} [color=green];
94 -> {68};
subgraph cluster_22 {
color=red
@@ -296,7 +292,6 @@ digraph flowFromTwoInplaceLambdas_kt {
}
122 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
102 [label="Postponed exit from lambda"];
103 [label="Postponed enter to lambda"];
subgraph cluster_26 {
color=blue
@@ -312,6 +307,7 @@ digraph flowFromTwoInplaceLambdas_kt {
129 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
104 [label="Postponed exit from lambda"];
102 [label="Postponed exit from lambda"];
105 [label="Function call: R|/run2|<R|kotlin/Int?|>(...)" style="filled" fillcolor=yellow];
106 [label="Access variable R|<local>/p|"];
107 [label="Smart cast: R|<local>/p|"];
@@ -331,12 +327,12 @@ digraph flowFromTwoInplaceLambdas_kt {
98 -> {99};
99 -> {100};
100 -> {101};
101 -> {116};
101 -> {102} [color=red];
101 -> {103 116};
101 -> {102} [style=dotted];
101 -> {116} [style=dashed];
102 -> {103};
103 -> {123};
103 -> {104} [color=red];
102 -> {105};
103 -> {123 105};
103 -> {104} [style=dotted];
103 -> {123} [style=dashed];
104 -> {105};
105 -> {106};
@@ -355,16 +351,14 @@ digraph flowFromTwoInplaceLambdas_kt {
119 -> {120};
120 -> {121};
121 -> {122};
122 -> {105} [color=red];
122 -> {102} [color=green];
122 -> {102};
123 -> {124};
124 -> {125};
125 -> {126};
126 -> {127};
127 -> {128};
128 -> {129};
129 -> {105} [color=red];
129 -> {104} [color=green];
129 -> {104};
subgraph cluster_28 {
color=red
@@ -390,7 +384,6 @@ digraph flowFromTwoInplaceLambdas_kt {
}
157 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
137 [label="Postponed exit from lambda"];
138 [label="Postponed enter to lambda"];
subgraph cluster_32 {
color=blue
@@ -406,6 +399,7 @@ digraph flowFromTwoInplaceLambdas_kt {
164 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
139 [label="Postponed exit from lambda"];
137 [label="Postponed exit from lambda"];
140 [label="Function call: R|/run2|<R|kotlin/Int?|>(...)" style="filled" fillcolor=yellow];
141 [label="Access variable R|<local>/p|"];
142 [label="Smart cast: R|<local>/p|"];
@@ -425,12 +419,12 @@ digraph flowFromTwoInplaceLambdas_kt {
133 -> {134};
134 -> {135};
135 -> {136};
136 -> {151};
136 -> {137} [color=red];
136 -> {138 151};
136 -> {137} [style=dotted];
136 -> {151} [style=dashed];
137 -> {138};
138 -> {158};
138 -> {139} [color=red];
137 -> {140};
138 -> {158 140};
138 -> {139} [style=dotted];
138 -> {158} [style=dashed];
139 -> {140};
140 -> {141};
@@ -449,16 +443,14 @@ digraph flowFromTwoInplaceLambdas_kt {
154 -> {155};
155 -> {156};
156 -> {157};
157 -> {140} [color=red];
157 -> {137} [color=green];
157 -> {137};
158 -> {159};
159 -> {160};
160 -> {161};
161 -> {162};
162 -> {163};
163 -> {164};
164 -> {140} [color=red];
164 -> {139} [color=green];
164 -> {139};
subgraph cluster_34 {
color=red
@@ -501,7 +493,6 @@ digraph flowFromTwoInplaceLambdas_kt {
}
197 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
176 [label="Postponed exit from lambda"];
177 [label="Postponed enter to lambda"];
subgraph cluster_40 {
color=blue
@@ -520,6 +511,7 @@ digraph flowFromTwoInplaceLambdas_kt {
207 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
178 [label="Postponed exit from lambda"];
176 [label="Postponed exit from lambda"];
179 [label="Function call: R|/run2|<R|kotlin/Int?|>(...)" style="filled" fillcolor=yellow];
180 [label="Access variable R|<local>/x|"];
181 [label="Smart cast: R|<local>/x|"];
@@ -537,12 +529,12 @@ digraph flowFromTwoInplaceLambdas_kt {
172 -> {173};
173 -> {174};
174 -> {175};
175 -> {188};
175 -> {176} [color=red];
175 -> {177 188};
175 -> {176} [style=dotted];
175 -> {188} [style=dashed];
176 -> {177};
177 -> {198};
177 -> {178} [color=red];
176 -> {179};
177 -> {198 179};
177 -> {178} [style=dotted];
177 -> {198} [style=dashed];
178 -> {179};
179 -> {180};
@@ -562,8 +554,7 @@ digraph flowFromTwoInplaceLambdas_kt {
194 -> {195};
195 -> {196};
196 -> {197};
197 -> {179} [color=red];
197 -> {176} [color=green];
197 -> {176};
198 -> {199};
199 -> {200};
200 -> {201};
@@ -573,8 +564,7 @@ digraph flowFromTwoInplaceLambdas_kt {
204 -> {205};
205 -> {206};
206 -> {207};
207 -> {179} [color=red];
207 -> {178} [color=green];
207 -> {178};
subgraph cluster_42 {
color=red
@@ -600,7 +590,6 @@ digraph flowFromTwoInplaceLambdas_kt {
}
235 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
215 [label="Postponed exit from lambda"];
216 [label="Postponed enter to lambda"];
subgraph cluster_46 {
color=blue
@@ -616,6 +605,7 @@ digraph flowFromTwoInplaceLambdas_kt {
242 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
217 [label="Postponed exit from lambda"];
215 [label="Postponed exit from lambda"];
218 [label="Function call: R|/run2|<R|kotlin/Int?|>(...)" style="filled" fillcolor=yellow];
219 [label="Access variable R|<local>/p|"];
220 [label="Smart cast: R|<local>/p|"];
@@ -635,12 +625,12 @@ digraph flowFromTwoInplaceLambdas_kt {
211 -> {212};
212 -> {213};
213 -> {214};
214 -> {229};
214 -> {215} [color=red];
214 -> {216 229};
214 -> {215} [style=dotted];
214 -> {229} [style=dashed];
215 -> {216};
216 -> {236};
216 -> {217} [color=red];
215 -> {218};
216 -> {236 218};
216 -> {217} [style=dotted];
216 -> {236} [style=dashed];
217 -> {218};
218 -> {219};
@@ -659,16 +649,14 @@ digraph flowFromTwoInplaceLambdas_kt {
232 -> {233};
233 -> {234};
234 -> {235};
235 -> {218} [color=red];
235 -> {215} [color=green];
235 -> {215};
236 -> {237};
237 -> {238};
238 -> {239};
239 -> {240};
240 -> {241};
241 -> {242};
242 -> {218} [color=red];
242 -> {217} [color=green];
242 -> {217};
subgraph cluster_48 {
color=red
@@ -692,7 +680,6 @@ digraph flowFromTwoInplaceLambdas_kt {
}
262 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
247 [label="Postponed exit from lambda"];
248 [label="Postponed enter to lambda"];
subgraph cluster_52 {
color=blue
@@ -707,6 +694,7 @@ digraph flowFromTwoInplaceLambdas_kt {
268 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
249 [label="Postponed exit from lambda"];
247 [label="Postponed exit from lambda"];
250 [label="Function call: R|/run2|<R|kotlin/Int|>(...)" style="filled" fillcolor=yellow];
251 [label="Access variable R|<local>/x|"];
252 [label="Access variable R|kotlin/String.length|"];
@@ -717,12 +705,12 @@ digraph flowFromTwoInplaceLambdas_kt {
243 -> {244};
244 -> {245};
245 -> {246};
246 -> {255};
246 -> {247} [color=red];
246 -> {248 255};
246 -> {247} [style=dotted];
246 -> {255} [style=dashed];
247 -> {248};
248 -> {263};
248 -> {249} [color=red];
247 -> {250};
248 -> {263 250};
248 -> {249} [style=dotted];
248 -> {263} [style=dashed];
249 -> {250};
250 -> {251};
@@ -736,15 +724,13 @@ digraph flowFromTwoInplaceLambdas_kt {
259 -> {260};
260 -> {261};
261 -> {262};
262 -> {250} [color=red];
262 -> {247} [color=green];
262 -> {247};
263 -> {264};
264 -> {265};
265 -> {266};
266 -> {267};
267 -> {268};
268 -> {250} [color=red];
268 -> {249} [color=green];
268 -> {249};
subgraph cluster_54 {
color=red
@@ -768,7 +754,6 @@ digraph flowFromTwoInplaceLambdas_kt {
}
300 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
275 [label="Postponed exit from lambda"];
276 [label="Postponed enter to lambda"];
subgraph cluster_58 {
color=blue
@@ -783,6 +768,7 @@ digraph flowFromTwoInplaceLambdas_kt {
306 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
277 [label="Postponed exit from lambda"];
275 [label="Postponed exit from lambda"];
278 [label="Function call: R|/run2|<R|kotlin/Unit|>(...)" style="filled" fillcolor=yellow];
subgraph cluster_60 {
color=blue
@@ -816,12 +802,12 @@ digraph flowFromTwoInplaceLambdas_kt {
271 -> {272};
272 -> {273};
273 -> {274};
274 -> {295};
274 -> {275} [color=red];
274 -> {276 295};
274 -> {275} [style=dotted];
274 -> {295} [style=dashed];
275 -> {276};
276 -> {301};
276 -> {277} [color=red];
275 -> {278};
276 -> {301 278};
276 -> {277} [style=dotted];
276 -> {301} [style=dashed];
277 -> {278};
278 -> {279};
@@ -845,15 +831,13 @@ digraph flowFromTwoInplaceLambdas_kt {
297 -> {298};
298 -> {299};
299 -> {300};
300 -> {278} [color=red];
300 -> {275} [color=green];
300 -> {275};
301 -> {302};
302 -> {303};
303 -> {306};
303 -> {304} [style=dotted];
304 -> {305} [style=dotted];
305 -> {306} [style=dotted];
306 -> {278} [color=red];
306 -> {277} [color=green];
306 -> {277};
}
@@ -75,7 +75,7 @@ fun test5(x: Any?, q: String?) {
fun test6() {
val x: String
// not necessarily initialized in second lambda (may call in any order)
run2({ x = ""; x.length }, { x.length })
run2({ x = ""; x.length }, { <!UNINITIALIZED_VARIABLE!>x<!>.length })
x.length // initialized here
}
@@ -62,8 +62,8 @@ digraph initBlockAndInPlaceLambda_kt {
9 -> {10};
10 -> {11 15};
11 -> {12};
12 -> {19};
12 -> {13} [color=red];
12 -> {19 14};
12 -> {13} [style=dotted];
12 -> {19} [style=dashed];
13 -> {14};
14 -> {15};
@@ -77,8 +77,7 @@ digraph initBlockAndInPlaceLambda_kt {
22 -> {23};
23 -> {24};
24 -> {25};
25 -> {14} [color=red];
25 -> {13} [color=green];
25 -> {13};
subgraph cluster_7 {
color=red
@@ -99,10 +99,11 @@ digraph inplaceLambdaInControlFlowExpressions_kt {
21 -> {29};
22 -> {23};
23 -> {24};
24 -> {33};
24 -> {25} [color=red];
24 -> {33 26};
24 -> {25} [style=dotted];
24 -> {33} [style=dashed];
25 -> {26};
25 -> {29} [color=red];
25 -> {26} [color=green];
26 -> {27};
27 -> {28};
28 -> {29};
@@ -113,8 +114,7 @@ digraph inplaceLambdaInControlFlowExpressions_kt {
34 -> {35};
35 -> {36};
36 -> {37};
37 -> {29} [color=red];
37 -> {25} [color=green];
37 -> {25};
subgraph cluster_11 {
color=red
@@ -173,10 +173,11 @@ digraph inplaceLambdaInControlFlowExpressions_kt {
40 -> {41 48};
41 -> {42};
42 -> {43};
43 -> {58};
43 -> {44} [color=red];
43 -> {58 45};
43 -> {44} [style=dotted];
43 -> {58} [style=dashed];
44 -> {45};
44 -> {54} [color=red];
44 -> {45} [color=green];
45 -> {46};
46 -> {47};
47 -> {54 48};
@@ -194,8 +195,7 @@ digraph inplaceLambdaInControlFlowExpressions_kt {
59 -> {60};
60 -> {61};
61 -> {62};
62 -> {54} [color=red];
62 -> {44} [color=green];
62 -> {44};
subgraph cluster_20 {
color=red
@@ -225,10 +225,11 @@ digraph inplaceLambdaInControlFlowExpressions_kt {
}
63 -> {64};
64 -> {65};
65 -> {72};
65 -> {66} [color=red];
65 -> {72 67};
65 -> {66} [style=dotted];
65 -> {72} [style=dashed];
66 -> {67};
66 -> {68} [color=red];
66 -> {67} [color=green];
67 -> {68};
68 -> {69};
69 -> {70};
@@ -237,7 +238,6 @@ digraph inplaceLambdaInControlFlowExpressions_kt {
73 -> {74};
74 -> {75};
75 -> {76};
76 -> {68} [color=red];
76 -> {66} [color=green];
76 -> {66};
}
+1 -1
View File
@@ -407,7 +407,7 @@ digraph jumps_kt {
}
130 -> {131};
131 -> {132};
132 -> {133 137};
132 -> {133 137 134};
132 -> {137} [style=dashed];
133 -> {134};
133 -> {132} [color=green style=dashed];
@@ -26,34 +26,34 @@ digraph lambdaAsReturnOfLambda_kt {
}
13 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
3 [label="Postponed exit from lambda"];
4 [label="Jump: ^@run lambda@fun <anonymous>(foo: R|kotlin/String|): R|kotlin/Unit| <inline=Unknown> {
3 [label="Jump: ^@run lambda@fun <anonymous>(foo: R|kotlin/String|): R|kotlin/Unit| <inline=Unknown> {
R|/bar|(R|<local>/foo|)
}
"];
5 [label="Stub" style="filled" fillcolor=gray];
6 [label="Exit block" style="filled" fillcolor=gray];
4 [label="Stub" style="filled" fillcolor=gray];
5 [label="Exit block" style="filled" fillcolor=gray];
}
7 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
6 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
7 [label="Postponed exit from lambda"];
16 [label="Postponed exit from lambda"];
17 [label="Function call: R|/run|<R|(kotlin/String) -> kotlin/Unit|>(...)" style="filled" fillcolor=yellow];
18 [label="Exit property" style="filled" fillcolor=red];
}
14 -> {15};
15 -> {16 0};
15 -> {16 0 17};
15 -> {0} [style=dashed];
16 -> {17};
17 -> {18};
0 -> {1};
1 -> {2};
2 -> {3 8};
2 -> {7 3 8};
2 -> {8} [style=dashed];
3 -> {4};
4 -> {7};
3 -> {6};
3 -> {4} [style=dotted];
4 -> {5} [style=dotted];
5 -> {6} [style=dotted];
6 -> {7} [style=dotted];
7 -> {17};
8 -> {9};
9 -> {10};
10 -> {11};
@@ -97,9 +97,10 @@ digraph lambdaReturningObject_kt {
}
21 -> {22};
22 -> {23};
23 -> {24 29};
23 -> {24 29 25};
23 -> {29} [style=dashed];
24 -> {25};
24 -> {26} [color=red];
24 -> {25} [color=green];
25 -> {26};
26 -> {27};
27 -> {28};
@@ -75,7 +75,7 @@ digraph lambdas_kt {
12 -> {20};
13 -> {14};
14 -> {15};
15 -> {16 23};
15 -> {16 23 17};
15 -> {23} [style=dashed];
16 -> {17};
16 -> {15} [color=green style=dashed];
@@ -219,7 +219,7 @@ digraph lambdas_kt {
}
63 -> {64};
64 -> {65};
65 -> {66 72};
65 -> {66 72 67};
65 -> {72} [style=dashed];
66 -> {67};
66 -> {65} [color=green style=dashed];
@@ -270,7 +270,7 @@ digraph lambdas_kt {
}
79 -> {80};
80 -> {81};
81 -> {82 88};
81 -> {82 88 83};
81 -> {88} [style=dashed];
82 -> {83};
82 -> {81} [color=green style=dashed];
@@ -193,7 +193,7 @@ digraph localClassesWithImplicit_kt {
}
36 -> {37};
37 -> {38};
38 -> {39 45};
38 -> {39 45 40};
38 -> {45} [style=dashed];
39 -> {40};
39 -> {38} [color=green style=dashed];
@@ -269,7 +269,7 @@ digraph localClassesWithImplicit_kt {
}
73 -> {74};
74 -> {75};
75 -> {76 82};
75 -> {76 82 77};
75 -> {82} [style=dashed];
76 -> {77};
76 -> {75} [color=green style=dashed];
@@ -398,7 +398,7 @@ digraph localClassesWithImplicit_kt {
}
102 -> {103};
103 -> {104};
104 -> {105 111};
104 -> {105 111 106};
104 -> {111} [style=dashed];
105 -> {106};
105 -> {104} [color=green style=dashed];
@@ -474,7 +474,7 @@ digraph localClassesWithImplicit_kt {
}
139 -> {140};
140 -> {141};
141 -> {142 148};
141 -> {142 148 143};
141 -> {148} [style=dashed];
142 -> {143};
142 -> {141} [color=green style=dashed];
@@ -42,11 +42,11 @@ digraph postponedLambdaInConstructor_kt {
}
22 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
15 [label="Postponed exit from lambda"];
16 [label="Exit block"];
15 [label="Exit block"];
}
17 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
16 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
17 [label="Postponed exit from lambda"];
8 [label="Postponed exit from lambda"];
9 [label="Function call: R|<local>/s|.R|kotlin/let|<R|kotlin/String|, R|() -> kotlin/String|>(...)" style="filled" fillcolor=yellow];
10 [label="Delegated constructor call: super<R|A|>(...)" style="filled" fillcolor=yellow];
@@ -54,20 +54,21 @@ digraph postponedLambdaInConstructor_kt {
}
5 -> {6};
6 -> {7};
7 -> {12};
7 -> {8} [color=red];
7 -> {12 9};
7 -> {8} [style=dotted];
7 -> {12} [style=dashed];
8 -> {9};
8 -> {10} [color=red];
8 -> {9} [color=green];
9 -> {10};
10 -> {11};
12 -> {13};
13 -> {14};
14 -> {15 18};
14 -> {17 15 18};
14 -> {18} [style=dashed];
15 -> {16};
16 -> {17};
16 -> {8};
17 -> {10} [color=red];
17 -> {8} [color=green];
17 -> {9} [color=green];
18 -> {19};
19 -> {20};
20 -> {21};
@@ -47,7 +47,7 @@ digraph postponedLambdas_kt {
5 -> {6};
6 -> {7};
7 -> {8};
8 -> {9 13};
8 -> {9 13 10};
8 -> {13} [style=dashed];
9 -> {10};
9 -> {8} [color=green style=dashed];
@@ -227,7 +227,7 @@ digraph propertiesAndInitBlocks_kt {
79 [label="Exit property" style="filled" fillcolor=red];
}
75 -> {76};
76 -> {77 24};
76 -> {77 24 78};
76 -> {24} [style=dashed];
77 -> {78};
77 -> {76} [color=green style=dashed];
@@ -91,8 +91,8 @@ digraph returnValuesFromLambda_kt {
}
12 -> {13};
13 -> {14};
14 -> {20};
14 -> {15} [color=red];
14 -> {20 16};
14 -> {15} [style=dotted];
14 -> {20} [style=dashed];
15 -> {16};
16 -> {17};
@@ -116,8 +116,7 @@ digraph returnValuesFromLambda_kt {
34 -> {35};
35 -> {36};
36 -> {37};
37 -> {16} [color=red];
37 -> {15} [color=green];
37 -> {15};
subgraph cluster_12 {
color=red
@@ -148,8 +147,8 @@ digraph returnValuesFromLambda_kt {
}
38 -> {39};
39 -> {40};
40 -> {46};
40 -> {41} [color=red];
40 -> {46 42};
40 -> {41} [style=dotted];
40 -> {46} [style=dashed];
41 -> {42};
42 -> {43};
@@ -162,8 +161,7 @@ digraph returnValuesFromLambda_kt {
49 -> {50} [style=dotted];
50 -> {51} [style=dotted];
51 -> {52} [style=dotted];
52 -> {42} [color=red];
52 -> {41} [color=green];
52 -> {41};
subgraph cluster_16 {
color=red
@@ -195,7 +193,7 @@ digraph returnValuesFromLambda_kt {
53 -> {54};
54 -> {55};
55 -> {62};
55 -> {56} [color=red];
55 -> {56 57} [style=dotted];
55 -> {62} [style=dashed];
56 -> {57} [style=dotted];
57 -> {58} [style=dotted];
@@ -209,6 +207,6 @@ digraph returnValuesFromLambda_kt {
64 -> {65} [style=dotted];
65 -> {66} [style=dotted];
66 -> {67} [style=dotted];
67 -> {56 57} [style=dotted];
67 -> {56} [style=dotted];
}
@@ -37,8 +37,8 @@ digraph classCallInLambda_kt {
0 -> {1};
1 -> {2};
2 -> {3};
3 -> {10};
3 -> {4} [color=red];
3 -> {10 5};
3 -> {4} [style=dotted];
3 -> {10} [style=dashed];
4 -> {5};
5 -> {6};
@@ -51,7 +51,6 @@ digraph classCallInLambda_kt {
12 -> {13};
13 -> {14};
14 -> {15};
15 -> {5} [color=red];
15 -> {4} [color=green];
15 -> {4};
}
@@ -502,7 +502,7 @@ digraph returns_kt {
172 -> {173};
173 -> {174};
174 -> {175};
175 -> {176 180};
175 -> {176 180 177};
175 -> {180} [style=dashed];
176 -> {177};
177 -> {178};
@@ -127,10 +127,11 @@ digraph incorrectSmartcastToNothing_kt {
32 -> {33};
33 -> {34 38};
34 -> {35};
35 -> {46};
35 -> {36} [color=red];
35 -> {46 37};
35 -> {36} [style=dotted];
35 -> {46} [style=dashed];
36 -> {37};
36 -> {41} [color=red];
36 -> {37} [color=green];
37 -> {38};
38 -> {41 39};
39 -> {40};
@@ -145,7 +146,6 @@ digraph incorrectSmartcastToNothing_kt {
49 -> {50};
50 -> {51};
51 -> {52};
52 -> {41} [color=red];
52 -> {36} [color=green];
52 -> {36};
}
@@ -87,8 +87,8 @@ digraph inPlaceLambdas_kt {
15 -> {23};
16 -> {17};
17 -> {18};
18 -> {26};
18 -> {19} [color=red];
18 -> {26 20};
18 -> {19} [style=dotted];
18 -> {26} [style=dashed];
19 -> {20};
20 -> {21};
@@ -102,8 +102,7 @@ digraph inPlaceLambdas_kt {
29 -> {30};
30 -> {31};
31 -> {32};
32 -> {20} [color=red];
32 -> {19} [color=green];
32 -> {19};
subgraph cluster_11 {
color=red
@@ -135,8 +134,8 @@ digraph inPlaceLambdas_kt {
}
33 -> {34};
34 -> {35};
35 -> {43};
35 -> {36} [color=red];
35 -> {43 37};
35 -> {36} [style=dotted];
35 -> {43} [style=dashed];
36 -> {37};
37 -> {38};
@@ -149,8 +148,7 @@ digraph inPlaceLambdas_kt {
45 -> {46};
46 -> {47};
47 -> {48};
48 -> {37} [color=red];
48 -> {36} [color=green];
48 -> {36};
subgraph cluster_15 {
color=red
@@ -214,8 +212,8 @@ digraph inPlaceLambdas_kt {
56 -> {67};
57 -> {58};
58 -> {59};
59 -> {70};
59 -> {60} [color=red];
59 -> {70 61};
59 -> {60} [style=dotted];
59 -> {70} [style=dashed];
60 -> {61};
61 -> {62};
@@ -235,7 +233,6 @@ digraph inPlaceLambdas_kt {
76 -> {77};
77 -> {78};
78 -> {79};
79 -> {61} [color=red];
79 -> {60} [color=green];
79 -> {60};
}
@@ -216,10 +216,11 @@ digraph lambdaInWhenBranch_kt {
45 -> {46};
46 -> {47};
47 -> {48};
48 -> {82};
48 -> {49} [color=red];
48 -> {82 50};
48 -> {49} [style=dotted];
48 -> {82} [style=dashed];
49 -> {50};
49 -> {53} [color=red];
49 -> {50} [color=green];
50 -> {51};
51 -> {52};
52 -> {53};
@@ -255,7 +256,6 @@ digraph lambdaInWhenBranch_kt {
83 -> {84};
84 -> {85};
85 -> {86};
86 -> {53} [color=red];
86 -> {49} [color=green];
86 -> {49};
}
@@ -304,8 +304,8 @@ digraph implicitReceivers_kt {
82 -> {83};
83 -> {84};
84 -> {85};
85 -> {90};
85 -> {86} [color=red];
85 -> {90 87};
85 -> {86} [style=dotted];
85 -> {90} [style=dashed];
86 -> {87};
87 -> {88};
@@ -313,19 +313,19 @@ digraph implicitReceivers_kt {
90 -> {91};
91 -> {92};
92 -> {93};
93 -> {98};
93 -> {94} [color=red];
93 -> {98 95};
93 -> {94} [style=dotted];
93 -> {98} [style=dashed];
94 -> {95};
94 -> {87} [color=red];
94 -> {95} [color=green];
95 -> {96};
96 -> {97};
97 -> {87} [color=red];
97 -> {86} [color=green];
97 -> {86};
98 -> {99};
99 -> {100};
100 -> {101};
101 -> {110};
101 -> {102} [color=red];
101 -> {110 103};
101 -> {102} [style=dotted];
101 -> {110} [style=dashed];
102 -> {103};
103 -> {104};
@@ -334,7 +334,7 @@ digraph implicitReceivers_kt {
106 -> {107};
107 -> {108};
108 -> {109};
109 -> {94} [color=green];
109 -> {94};
110 -> {111};
111 -> {112};
112 -> {113};
@@ -344,8 +344,7 @@ digraph implicitReceivers_kt {
116 -> {117};
117 -> {118};
118 -> {119};
119 -> {103} [color=red];
119 -> {102} [color=green];
119 -> {102};
subgraph cluster_32 {
color=red
@@ -187,7 +187,7 @@ digraph safeCalls_kt {
56 -> {57};
57 -> {63 58};
58 -> {59};
59 -> {60 69};
59 -> {60 69 61};
59 -> {69} [style=dashed];
60 -> {61};
61 -> {64};
@@ -292,7 +292,7 @@ digraph safeCalls_kt {
95 -> {96 106};
96 -> {97};
97 -> {112};
97 -> {98} [color=red];
97 -> {98 99} [style=dotted];
97 -> {112} [style=dashed];
98 -> {99} [style=dotted];
99 -> {100} [style=dotted];
@@ -314,6 +314,6 @@ digraph safeCalls_kt {
114 -> {115} [style=dotted];
115 -> {116} [style=dotted];
116 -> {117} [style=dotted];
117 -> {98 99} [style=dotted];
117 -> {98} [style=dotted];
}
@@ -295,8 +295,8 @@ digraph smartcastToNothing_kt {
91 -> {92};
92 -> {93 97};
93 -> {94};
94 -> {100};
94 -> {95} [color=red];
94 -> {100 96};
94 -> {95} [style=dotted];
94 -> {100} [style=dashed];
95 -> {96};
96 -> {97};
@@ -307,8 +307,7 @@ digraph smartcastToNothing_kt {
102 -> {103};
103 -> {104};
104 -> {105};
105 -> {96} [color=red];
105 -> {95} [color=green];
105 -> {95};
subgraph cluster_26 {
color=red
@@ -88,8 +88,8 @@ digraph complexPostponedCfg_kt {
6 -> {7};
7 -> {8};
8 -> {9};
9 -> {18};
9 -> {10} [color=red];
9 -> {18 11};
9 -> {10} [style=dotted];
9 -> {18} [style=dashed];
10 -> {11};
11 -> {12};
@@ -101,14 +101,14 @@ digraph complexPostponedCfg_kt {
16 -> {17} [style=dotted];
18 -> {19};
19 -> {20};
20 -> {25};
20 -> {21} [color=red];
20 -> {22 25};
20 -> {21} [style=dotted];
20 -> {25} [style=dashed];
21 -> {22};
21 -> {11} [color=red];
21 -> {22} [color=green];
22 -> {23};
23 -> {24};
24 -> {11} [color=red];
24 -> {10} [color=green];
24 -> {10};
25 -> {26};
26 -> {27};
27 -> {28};
@@ -116,14 +116,13 @@ digraph complexPostponedCfg_kt {
29 -> {30};
30 -> {31};
31 -> {32};
32 -> {37};
32 -> {33} [color=red];
32 -> {37 34};
32 -> {33} [style=dotted];
32 -> {37} [style=dashed];
33 -> {34};
34 -> {35};
35 -> {36};
36 -> {11} [color=red];
36 -> {21} [color=green];
36 -> {21};
37 -> {38};
38 -> {39};
39 -> {40};
@@ -132,7 +131,6 @@ digraph complexPostponedCfg_kt {
42 -> {43};
43 -> {44};
44 -> {45};
45 -> {34} [color=red];
45 -> {33} [color=green];
45 -> {33};
}
@@ -34,8 +34,8 @@ digraph callsInPlace_kt {
0 -> {1};
1 -> {2};
2 -> {3};
3 -> {10};
3 -> {4} [color=red];
3 -> {10 5};
3 -> {4} [style=dotted];
3 -> {10} [style=dashed];
4 -> {5};
5 -> {6};
@@ -47,8 +47,7 @@ digraph callsInPlace_kt {
12 -> {13};
13 -> {14};
14 -> {15};
15 -> {5} [color=red];
15 -> {4} [color=green];
15 -> {4};
subgraph cluster_4 {
color=red
@@ -78,7 +77,7 @@ digraph callsInPlace_kt {
16 -> {17};
17 -> {18};
18 -> {19};
19 -> {20 24};
19 -> {20 24 21};
19 -> {24} [style=dashed];
20 -> {21};
20 -> {19} [color=green style=dashed];
@@ -108,8 +107,8 @@ digraph callsInPlace_kt {
}
41 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
32 [label="Postponed exit from lambda"];
33 [label="Const: Int(10)"];
32 [label="Postponed exit from lambda"];
34 [label="Function call: R|kotlin/repeat|(...)" style="filled" fillcolor=yellow];
35 [label="Exit block"];
}
@@ -117,9 +116,9 @@ digraph callsInPlace_kt {
}
29 -> {30};
30 -> {31};
31 -> {32 37};
31 -> {32 33 37};
31 -> {37} [style=dashed];
32 -> {33};
32 -> {34};
32 -> {31} [color=green style=dashed];
33 -> {34};
34 -> {35};
@@ -162,8 +161,8 @@ digraph callsInPlace_kt {
42 -> {43};
43 -> {44};
44 -> {45};
45 -> {50};
45 -> {46} [color=red];
45 -> {50 47};
45 -> {46} [style=dotted];
45 -> {50} [style=dashed];
46 -> {47};
47 -> {48};
@@ -176,8 +175,7 @@ digraph callsInPlace_kt {
55 -> {56};
56 -> {57};
57 -> {58};
58 -> {47} [color=red];
58 -> {46} [color=green];
58 -> {46};
subgraph cluster_16 {
color=red
@@ -211,8 +209,8 @@ digraph callsInPlace_kt {
59 -> {60};
60 -> {61};
61 -> {62};
62 -> {67};
62 -> {63} [color=red];
62 -> {67 64};
62 -> {63} [style=dotted];
62 -> {67} [style=dashed];
63 -> {64};
64 -> {65};
@@ -225,8 +223,7 @@ digraph callsInPlace_kt {
72 -> {73};
73 -> {74};
74 -> {75};
75 -> {64} [color=red];
75 -> {63} [color=green];
75 -> {63};
subgraph cluster_20 {
color=red
@@ -264,7 +261,6 @@ digraph callsInPlace_kt {
}
100 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
85 [label="Postponed exit from lambda"];
86 [label="Postponed enter to lambda"];
subgraph cluster_26 {
color=blue
@@ -278,6 +274,7 @@ digraph callsInPlace_kt {
95 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
87 [label="Postponed exit from lambda"];
85 [label="Postponed exit from lambda"];
88 [label="Function call: R|/myRun|(...)" style="filled" fillcolor=yellow];
89 [label="Exit block"];
}
@@ -285,11 +282,11 @@ digraph callsInPlace_kt {
}
82 -> {83};
83 -> {84};
84 -> {85 96};
84 -> {85 86 96};
84 -> {96} [style=dashed];
85 -> {86};
85 -> {88};
85 -> {84} [color=green style=dashed];
86 -> {87 91};
86 -> {87 91 88};
86 -> {91} [style=dashed];
87 -> {88};
87 -> {86} [color=green style=dashed];
@@ -324,7 +321,6 @@ digraph callsInPlace_kt {
}
114 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
104 [label="Postponed exit from lambda"];
105 [label="Postponed enter to lambda"];
subgraph cluster_32 {
color=blue
@@ -338,6 +334,7 @@ digraph callsInPlace_kt {
119 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
106 [label="Postponed exit from lambda"];
104 [label="Postponed exit from lambda"];
107 [label="Function call: R|/myRun|(...)" style="filled" fillcolor=yellow];
108 [label="Exit block"];
}
@@ -345,11 +342,11 @@ digraph callsInPlace_kt {
}
101 -> {102};
102 -> {103};
103 -> {104 110};
103 -> {104 105 110};
103 -> {110} [style=dashed];
104 -> {105};
104 -> {107};
104 -> {103} [color=green style=dashed];
105 -> {106 115};
105 -> {106 115 107};
105 -> {115} [style=dashed];
106 -> {107};
106 -> {105} [color=green style=dashed];
@@ -408,7 +405,7 @@ digraph callsInPlace_kt {
}
125 -> {126};
126 -> {127};
127 -> {128 132};
127 -> {128 132 129};
127 -> {132} [style=dashed];
128 -> {129};
129 -> {130};
@@ -66,8 +66,8 @@ digraph atLeastOnce_kt {
10 -> {11};
11 -> {12};
12 -> {13};
13 -> {20};
13 -> {14} [color=red];
13 -> {20 15};
13 -> {14} [style=dotted];
13 -> {20} [style=dashed];
14 -> {15};
14 -> {13} [color=green style=dashed];
@@ -80,8 +80,7 @@ digraph atLeastOnce_kt {
22 -> {23};
23 -> {24};
24 -> {25};
25 -> {15} [color=red];
25 -> {14} [color=green];
25 -> {14};
subgraph cluster_8 {
color=red
@@ -114,8 +113,8 @@ digraph atLeastOnce_kt {
26 -> {27};
27 -> {28};
28 -> {29};
29 -> {36};
29 -> {30} [color=red];
29 -> {36 31};
29 -> {30} [style=dotted];
29 -> {36} [style=dashed];
30 -> {31};
30 -> {29} [color=green style=dashed];
@@ -128,7 +127,6 @@ digraph atLeastOnce_kt {
38 -> {39};
39 -> {40};
40 -> {41};
41 -> {31} [color=red];
41 -> {30} [color=green];
41 -> {30};
}
@@ -66,7 +66,7 @@ digraph atMostOnce_kt {
10 -> {11};
11 -> {12};
12 -> {13};
13 -> {14 20};
13 -> {14 20 15};
13 -> {20} [style=dashed];
14 -> {15};
15 -> {16};
@@ -111,7 +111,7 @@ digraph atMostOnce_kt {
26 -> {27};
27 -> {28};
28 -> {29};
29 -> {30 36};
29 -> {30 36 31};
29 -> {36} [style=dashed];
30 -> {31};
31 -> {32};
@@ -66,8 +66,8 @@ digraph exactlyOnce_kt {
10 -> {11};
11 -> {12};
12 -> {13};
13 -> {20};
13 -> {14} [color=red];
13 -> {20 15};
13 -> {14} [style=dotted];
13 -> {20} [style=dashed];
14 -> {15};
15 -> {16};
@@ -79,8 +79,7 @@ digraph exactlyOnce_kt {
22 -> {23};
23 -> {24};
24 -> {25};
25 -> {15} [color=red];
25 -> {14} [color=green];
25 -> {14};
subgraph cluster_8 {
color=red
@@ -113,8 +112,8 @@ digraph exactlyOnce_kt {
26 -> {27};
27 -> {28};
28 -> {29};
29 -> {36};
29 -> {30} [color=red];
29 -> {36 31};
29 -> {30} [style=dotted];
29 -> {36} [style=dashed];
30 -> {31};
31 -> {32};
@@ -126,7 +125,6 @@ digraph exactlyOnce_kt {
38 -> {39};
39 -> {40};
40 -> {41};
41 -> {31} [color=red];
41 -> {30} [color=green];
41 -> {30};
}
@@ -76,7 +76,7 @@ digraph inPlaceLambda_kt {
15 -> {16};
16 -> {17};
17 -> {18};
18 -> {19 23};
18 -> {19 23 20};
18 -> {23} [style=dashed];
19 -> {20};
20 -> {21};
@@ -66,7 +66,7 @@ digraph unknown_kt {
10 -> {11};
11 -> {12};
12 -> {13};
13 -> {14 20};
13 -> {14 20 15};
13 -> {20} [style=dashed];
14 -> {15};
14 -> {13} [color=green style=dashed];
@@ -112,7 +112,7 @@ digraph unknown_kt {
26 -> {27};
27 -> {28};
28 -> {29};
29 -> {30 36};
29 -> {30 36 31};
29 -> {36} [style=dashed];
30 -> {31};
30 -> {29} [color=green style=dashed];
@@ -229,9 +229,10 @@ digraph delegateWithAnonymousObject_kt {
78 [label="Exit property" style="filled" fillcolor=red];
}
71 -> {72};
72 -> {73};
72 -> {73 74};
72 -> {26} [style=dashed];
73 -> {74};
73 -> {77} [color=red];
73 -> {74} [color=green];
74 -> {75};
75 -> {76};
76 -> {77};
@@ -40,7 +40,7 @@ digraph plusAssignWithLambdaInRhs_kt {
4 -> {5} [style=dotted];
5 -> {6} [style=dotted];
6 -> {7} [style=dotted];
7 -> {8 12} [style=dotted];
7 -> {8 12 9} [style=dotted];
7 -> {12} [style=dashed];
8 -> {9} [style=dotted];
8 -> {7} [color=green style=dotted];
@@ -135,7 +135,7 @@ digraph plusAssignWithLambdaInRhs_kt {
27 -> {28};
28 -> {29};
29 -> {30};
30 -> {31 37};
30 -> {31 37 32};
30 -> {37} [style=dashed];
31 -> {32};
32 -> {33};
@@ -146,7 +146,7 @@ digraph plusAssignWithLambdaInRhs_kt {
37 -> {38};
38 -> {39};
39 -> {40};
40 -> {41 45};
40 -> {41 45 42};
40 -> {45} [style=dashed];
41 -> {42};
41 -> {40} [color=green style=dashed];
@@ -105,7 +105,7 @@ finally {
14 -> {15};
15 -> {16};
16 -> {17};
17 -> {18 31};
17 -> {18 31 19};
17 -> {31} [style=dashed];
18 -> {19};
18 -> {17} [color=green style=dashed];
@@ -195,7 +195,7 @@ finally {
39 -> {40};
40 -> {41};
41 -> {42};
42 -> {43 56};
42 -> {43 56 44};
42 -> {56} [style=dashed];
43 -> {44};
44 -> {45};
@@ -40,7 +40,7 @@ class LocalPropertyAndCapturedWriteCollector private constructor() : ControlFlow
}
override fun visitPostponedLambdaEnterNode(node: PostponedLambdaEnterNode) {
lambdaOrLocalFunctionStack.add(node.fir)
lambdaOrLocalFunctionStack.add(node.fir.anonymousFunction)
}
override fun visitLocalFunctionDeclarationNode(node: LocalFunctionDeclarationNode, data: Nothing?) {
@@ -222,22 +222,15 @@ abstract class FirDataFlowAnalyzer(
exitCapturingStatement(anonymousFunction)
}
functionExitNode.mergeIncomingFlow()
if (postponedLambdaExitNode != null) {
// Data flow changed, need to recompute. TODO: this violates the "flow computed only once" principle.
postponedLambdaExitNode.mergeIncomingFlow()
} else {
// The current node should be `postponedLambdaExitNode` but we don't get a reference to it.
resetReceivers()
}
postponedLambdaExitNode?.mergeIncomingFlow()
resetReceivers() // roll back to state before function
return FirControlFlowGraphReferenceImpl(graph)
}
fun visitPostponedAnonymousFunction(anonymousFunctionExpression: FirAnonymousFunctionExpression) {
val anonymousFunction = anonymousFunctionExpression.anonymousFunction
getOrCreateLocalVariableAssignmentAnalyzer(anonymousFunction)?.visitPostponedAnonymousFunction(anonymousFunction)
val (enterNode, exitNode) = graphBuilder.visitPostponedAnonymousFunction(anonymousFunctionExpression)
enterNode.mergeIncomingFlow()
exitNode.mergeIncomingFlow()
graphBuilder.visitPostponedAnonymousFunction(anonymousFunctionExpression).mergeIncomingFlow()
}
fun exitAnonymousFunctionExpression(anonymousFunctionExpression: FirAnonymousFunctionExpression) {
@@ -626,11 +619,9 @@ abstract class FirDataFlowAnalyzer(
}
fun exitWhenExpression(whenExpression: FirWhenExpression, callCompleted: Boolean) {
val (whenExitNode, syntheticElseNode, mergePostponedLambdaExitsNode) =
graphBuilder.exitWhenExpression(whenExpression, callCompleted)
val (whenExitNode, syntheticElseNode) = graphBuilder.exitWhenExpression(whenExpression, callCompleted)
syntheticElseNode?.mergeWhenBranchEntryFlow()
whenExitNode.mergeIncomingFlow()
mergePostponedLambdaExitsNode?.mergeIncomingFlow()
}
fun exitWhenSubjectExpression(expression: FirWhenSubjectExpression) {
@@ -771,9 +762,7 @@ abstract class FirDataFlowAnalyzer(
}
fun exitTryExpression(callCompleted: Boolean) {
val (tryExpressionExitNode, mergePostponedLambdaExitsNode) = graphBuilder.exitTryExpression(callCompleted)
tryExpressionExitNode.mergeIncomingFlow()
mergePostponedLambdaExitsNode?.mergeIncomingFlow()
graphBuilder.exitTryExpression(callCompleted).mergeIncomingFlow()
}
// ----------------------------------- Resolvable call -----------------------------------
@@ -799,7 +788,7 @@ abstract class FirDataFlowAnalyzer(
}
fun exitSafeCall(safeCall: FirSafeCallExpression) {
val (node, mergePostponedLambdaExitsNode) = graphBuilder.exitSafeCall()
val node = graphBuilder.exitSafeCall()
node.mergeIncomingFlow { flow ->
// If there is only 1 previous node, then this is LHS of `a?.b ?: c`; then the null-case
// edge from `a` goes directly to `c` and this node's flow already assumes `b` executed.
@@ -813,7 +802,6 @@ abstract class FirDataFlowAnalyzer(
// (that requires a second level of implications: receiver != null => condition => effect).
flow.addAllConditionally(expressionVariable notEq null, node.lastPreviousNode.flow)
}
mergePostponedLambdaExitsNode?.mergeIncomingFlow()
}
fun exitResolvedQualifierNode(resolvedQualifier: FirResolvedQualifier) {
@@ -1172,7 +1160,7 @@ abstract class FirDataFlowAnalyzer(
}
fun exitElvis(elvisExpression: FirElvisExpression, isLhsNotNull: Boolean, callCompleted: Boolean) {
val (node, mergePostponedLambdaExitsNode) = graphBuilder.exitElvis(isLhsNotNull, callCompleted)
val node = graphBuilder.exitElvis(isLhsNotNull, callCompleted)
node.mergeIncomingFlow { flow ->
// If LHS is never null, then the edge from RHS is dead and this node's flow already contains
// all statements from LHS unconditionally.
@@ -1183,7 +1171,6 @@ abstract class FirDataFlowAnalyzer(
val elvisVariable = variableStorage.createSynthetic(elvisExpression)
flow.addAllConditionally(elvisVariable eq !rhs, node.firstPreviousNode.flow)
}
mergePostponedLambdaExitsNode?.mergeIncomingFlow()
}
// Callable reference
@@ -1223,7 +1210,10 @@ abstract class FirDataFlowAnalyzer(
private fun CFGNode<*>.buildIncomingFlow(): MutableFlow {
val previousFlows = previousNodes.mapNotNull {
val incomingEdgeKind = incomingEdges.getValue(it).kind
it.takeIf { incomingEdgeKind.usedInDfa || (isDead && incomingEdgeKind.usedInDeadDfa) }?.flow
if (if (isDead) !incomingEdgeKind.usedInDeadDfa else !incomingEdgeKind.usedInDfa) return@mapNotNull null
// `MergePostponedLambdaExitsNode` nodes form a parallel data flow graph. We never compute
// data flow for any of them until reaching a completed call.
if (it is MergePostponedLambdaExitsNode) it.mergeIncomingFlow() else it.flow
}
val result = logicSystem.joinFlow(previousFlows, union = this is UnionNodeMarker)
if (graphBuilder.lastNodeOrNull == this) {
@@ -63,13 +63,12 @@ class ControlFlowGraphBuilder {
private val postponedAnonymousFunctionNodes =
mutableMapOf<FirFunctionSymbol<*>, Pair<PostponedLambdaEnterNode, PostponedLambdaExitNode>>()
private val dataFlowSourcesForNextCompletedCall: Stack<MutableList<CFGNode<*>>> = stackOf()
private val postponedLambdaExits: Stack<MutableList<Pair<CFGNode<*>, EdgeKind>>> = stackOf()
private val loopConditionEnterNodes: NodeStorage<FirElement, LoopConditionEnterNode> = NodeStorage()
private val loopExitNodes: NodeStorage<FirLoop, LoopExitNode> = NodeStorage()
private val whenExitNodes: NodeStorage<FirWhenExpression, WhenExitNode> = NodeStorage()
private val whenBranchIndices: Stack<Map<FirWhenBranch, Int>> = stackOf()
private val binaryLogicExpressionExitNodes: Stack<AbstractBinaryExitNode<FirBinaryLogicExpression>> = stackOf()
@@ -199,8 +198,6 @@ class ControlFlowGraphBuilder {
}
// ----------------------------------- Anonymous function -----------------------------------
// TODO: this is ALL WRONG.
//
// There are two cases we need to distinguish.
//
// 1. Function calls can have contracts that specify lambdas as "called in place".
@@ -227,28 +224,28 @@ class ControlFlowGraphBuilder {
// |<--------------\ |
// \-----> [UNKNOWN] -----/
// \----------^
// This is already problematic, since all these lambdas should share ONE entry node
// to which control can return after AT_LEAST_ONCE and UNKNOWN lambdas. To make
// matters worse, if the call is not complete, then the lambdas inside it *and*
// other lambdas in whatever expression this is a part of can be resolved in any order,
// so the data flow cannot look like this - until some call is finally completed, there
// will be holes in the graph where some lambdas' subgraphs should be. Instead, we
// should be collecting the lambdas as they are being resolved, filling gaps in the
// control flow graph, and then redirecting the outgoing data flow edges into the next
// completed call node. Unfortunately, I'm not sure how this fits into the subgraph
// design. Also, touching the `PostponedLambda{Enter,Exit}Node`s in any way seem to
// break random stuff that probably looks at `node.fir` with zero regard as to what
// the node even means.
fun visitPostponedAnonymousFunction(anonymousFunctionExpression: FirAnonymousFunctionExpression): Pair<PostponedLambdaEnterNode, PostponedLambdaExitNode> {
val anonymousFunction = anonymousFunctionExpression.anonymousFunction
val enterNode = createPostponedLambdaEnterNode(anonymousFunction)
// To implement this, we create dummy enter+exit nodes, then as the call is resolved
// plop in the lambdas in between them and add looping/skipping edges depending
// on how many times the lambda is called (only known after we select a candidate
// for the call). Then, when the call is exited, we add edges from the dummy exit
// nodes instead of directly from lambdas.
//
// If the call is not complete, then it is not guaranteed that lambdas will be resolved
// before we have to create the function call node. In that case we can still add
// control flow edges from the dummy nodes, but not data flow edges as the data flow
// for them may not have been computed yet. Instead, these edges are redirected
// into the outer call. The outermost call *has* to be completed, so at some point
// all data will be unified in a single call node.
fun visitPostponedAnonymousFunction(anonymousFunctionExpression: FirAnonymousFunctionExpression): PostponedLambdaEnterNode {
// TODO: should only have 1 enter node for all lambdas in a single call.
val enterNode = createPostponedLambdaEnterNode(anonymousFunctionExpression)
val exitNode = createPostponedLambdaExitNode(anonymousFunctionExpression)
val symbol = anonymousFunction.symbol
val symbol = anonymousFunctionExpression.anonymousFunction.symbol
postponedAnonymousFunctionNodes[symbol] = enterNode to exitNode
addNewSimpleNode(enterNode)
addNewSimpleNode(exitNode, preferredKind = EdgeKind.DfgForward)
require(dataFlowSourcesForNextCompletedCall.isNotEmpty)
return enterNode to exitNode
addEdge(enterNode, exitNode)
postponedLambdaExits.top().add(exitNode to EdgeKind.Forward)
return enterNode
}
fun enterAnonymousFunction(anonymousFunction: FirAnonymousFunction): Pair<LocalFunctionDeclarationNode?, FunctionEnterNode> {
@@ -282,37 +279,20 @@ class ControlFlowGraphBuilder {
val graph = popGraph().also { graph ->
assert(graph.declaration == anonymousFunction)
assert(graph.exitNode == exitNode)
// TODO: disregarding the edges is probably not correct, though this should never find any nodes anyway
dataFlowSourcesForNextCompletedCall.topOrNull()?.removeAll { it.owner == graph }
}
val (postponedEnterNode, postponedExitNode) = postponedAnonymousFunctionNodes.remove(symbol)
?: return Triple(exitNode, null, graph).also { currentGraph.addSubGraph(graph) }
val invocationKind = anonymousFunction.invocationKind
var changedExitDataFlow = false
// Lambdas not called in-place behave as if called never, but with extra invalidation of all smart casts
// for all variables that they reassign. That second part is handled by `FirDataFlowAnalyzer`.
if (invocationKind?.isDefinitelyVisited() != true) {
// Data flow from enter -> exit already exists, only need to also mark that edge as control flow.
CFGNode.addJustKindEdge(postponedEnterNode, postponedExitNode, EdgeKind.CfgForward, propagateDeadness = true)
}
if (invocationKind?.canBeVisited() == true) {
val currentCallsPostponedLambdas = dataFlowSourcesForNextCompletedCall.top()
// Since the skipping edge goes to `postponedExitNode` rather than `exitNode`, if
// we try to merge data flow for not-definitely-called lambdas from `exitNode` into the next call
// we won't get a correct result. TODO: that seems hacky and points to the edges being wrong.
addEdge(exitNode, postponedExitNode, propagateDeadness = invocationKind.isDefinitelyVisited())
if (invocationKind.isDefinitelyVisited()) {
// When a call has lambda arguments that the function says it will call in place, control goes through
// all other arguments, then through the lambdas in parallel, then out of the function call. This parallel
// (in terms of ordering, not multi-threaded or w/e) execution is represented with the call being a union node.
// TODO: currently this is only done for data flow; control flow incorrectly pretends lambdas
// are called in the order they are provided to the call, which is wrong. This needs to be fixed. Somehow.
addEdge(exitNode, postponedExitNode, preferredKind = EdgeKind.CfgForward, propagateDeadness = true)
currentCallsPostponedLambdas.add(postponedExitNode)
} else {
addEdge(exitNode, postponedExitNode, propagateDeadness = invocationKind.isDefinitelyVisited())
changedExitDataFlow = true
// We had to create this edge so that if the lambda is postponed for so long that we exit the subgraph
// before visiting it, `orderNodes` can still find an ordering. Now we can kill it.
CFGNode.addJustKindEdge(postponedEnterNode, postponedExitNode, EdgeKind.DeadForward, propagateDeadness = false)
}
if (invocationKind.canBeRevisited()) {
addBackEdge(postponedExitNode, postponedEnterNode)
@@ -322,7 +302,7 @@ class ControlFlowGraphBuilder {
postponedEnterNode.addSubGraph(graph)
// May not be the current graph: `nearestCompletedCall(run { run { generic() } }, 1)`
postponedEnterNode.owner.addSubGraph(graph)
return Triple(exitNode, postponedExitNode.takeIf { changedExitDataFlow }, graph)
return Triple(exitNode, postponedExitNode, graph)
}
fun exitAnonymousFunctionExpression(anonymousFunctionExpression: FirAnonymousFunctionExpression): AnonymousFunctionExpressionExitNode {
@@ -332,28 +312,28 @@ class ControlFlowGraphBuilder {
}
private fun splitDataFlowForPostponedLambdas() {
dataFlowSourcesForNextCompletedCall.push(mutableListOf())
}
private fun MutableList<CFGNode<*>>.addPostponedLambdaDataFlowEdgesTo(node: CFGNode<*>) {
for (exitNode in this) {
// To avoid storing nodes from subgraphs in the list, we have PostponedLambdaExitNode instead of the real
// exit node of the lambda subgraph. The latter is the previous node of the former. Everything else is
// already a join node in this graph.
val functionExitOrMerge = if (exitNode is PostponedLambdaExitNode) exitNode.lastPreviousNode else exitNode
addEdge(functionExitOrMerge, node, preferredKind = EdgeKind.DfgForward, propagateDeadness = false)
}
postponedLambdaExits.push(mutableListOf())
}
private fun <T> unifyDataFlowFromPostponedLambdas(node: T, callCompleted: Boolean) where T : CFGNode<*>, T : UnionNodeMarker {
val currentLevelExits = dataFlowSourcesForNextCompletedCall.pop()
val currentLevelExits = postponedLambdaExits.pop()
if (currentLevelExits.isEmpty()) return
val nextLevelExits = dataFlowSourcesForNextCompletedCall.topOrNull().takeIf { !callCompleted }
val nextLevelExits = postponedLambdaExits.topOrNull().takeIf { !callCompleted }
if (nextLevelExits != null) {
// Call is incomplete, don't pass data flow from lambdas inside it to lambdas in the outer call.
nextLevelExits.addAll(currentLevelExits)
for ((exit, kind) in currentLevelExits) {
if (kind.usedInCfa) {
addEdge(exit, node, preferredKind = EdgeKind.CfgForward)
}
nextLevelExits.add(exit to EdgeKind.DfgForward)
}
} else {
currentLevelExits.addPostponedLambdaDataFlowEdgesTo(node)
for ((exit, kind) in currentLevelExits) {
// Since `node` is a union node, it is dead iff any input is dead. For once, `propagateDeadness`
// semantics are correct without an `updateDeadStatus`.
addEdge(exit, node, preferredKind = kind, propagateDeadness = kind.usedInCfa)
}
}
}
@@ -368,7 +348,7 @@ class ControlFlowGraphBuilder {
// \-> y -> ?? -> run#2 -/
//
// Ideally, we want to pretend that the lambdas are not called-in-place until we get
// to `f`, at which point the lambdas are guaranteed to be resolved and we should be
// to `f`, at which point the lambdas are guaranteed to be resolved, and we should be
// able to reconstruct the entire data flow. The problem is that the call/when/etc.
// exit nodes on the way from the lambda to the function call exit node can have
// statements attached to them, so unless we want to re-do all the work, it's too late
@@ -376,24 +356,31 @@ class ControlFlowGraphBuilder {
// they may reassign variables and so the data we've gathered about them should be
// invalidated. So what we do here is merge the data from the lambdas with the data
// obtained without them: this can only erase statements that are not provably correct.
private fun mergeDataFlowFromPostponedLambdas(node: CFGNode<*>, callCompleted: Boolean): MergePostponedLambdaExitsNode? {
val currentLevelExits = dataFlowSourcesForNextCompletedCall.pop()
if (currentLevelExits.isEmpty()) return null
//
// TODO: an alternative is to delay computing incoming flow for "branch result exit" nodes
// until the entire "when" is resolved; then either unify each branch's lambdas into its
// exit node, or create N union nodes (1/branch) and point them into the merge node.
private fun mergeDataFlowFromPostponedLambdas(node: CFGNode<*>, callCompleted: Boolean) {
val currentLevelExits = postponedLambdaExits.pop()
if (currentLevelExits.isEmpty()) return
val nextLevelExits = dataFlowSourcesForNextCompletedCall.topOrNull().takeIf { !callCompleted }
return if (nextLevelExits != null) {
// Call is incomplete, don't pass data flow from lambdas inside it to lambdas in the outer call.
// TODO: this is wrong, we don't necessarily have all the lambdas yet... Also,
// the lambdas in the list can come from different branches, and this should be
// more like merge(node, union(lambdas from branch 1), ..., union(from branch N)).
createMergePostponedLambdaExitsNode(node.fir).also {
addEdge(node, it)
currentLevelExits.addPostponedLambdaDataFlowEdgesTo(it)
nextLevelExits.add(it)
}
val nextLevelExits = postponedLambdaExits.topOrNull().takeIf { !callCompleted }
if (nextLevelExits != null) {
node.updateDeadStatus()
nextLevelExits += createMergePostponedLambdaExitsNode(node.fir).also {
addEdge(node, it) // copy liveness (deadness?) from `node`
for ((exit, kind) in currentLevelExits) {
if (kind.usedInCfa) {
addEdge(exit, node, preferredKind = EdgeKind.CfgForward, propagateDeadness = false)
}
addEdge(exit, it, preferredKind = EdgeKind.DfgForward, propagateDeadness = false)
}
} to EdgeKind.DfgForward
} else {
currentLevelExits.addPostponedLambdaDataFlowEdgesTo(node)
null
for ((exit, kind) in currentLevelExits) {
// `node` is a merge node for many inputs anyhow so someone will call `updateDeadStatus` on it.
addEdge(exit, node, preferredKind = kind, propagateDeadness = false)
}
}
}
@@ -709,7 +696,6 @@ class ControlFlowGraphBuilder {
val node = createWhenEnterNode(whenExpression)
addNewSimpleNode(node)
whenExitNodes.push(createWhenExitNode(whenExpression))
whenBranchIndices.push(whenExpression.branches.mapIndexed { index, branch -> branch to index }.toMap())
notCompletedFunctionCalls.push(mutableListOf())
levelCounter++
splitDataFlowForPostponedLambdas()
@@ -721,7 +707,6 @@ class ControlFlowGraphBuilder {
}
fun enterWhenBranchCondition(whenBranch: FirWhenBranch): WhenBranchConditionEnterNode {
levelCounter += whenBranchIndices.top().getValue(whenBranch)
return createWhenBranchConditionEnterNode(whenBranch).also { addNewSimpleNode(it) }.also { levelCounter++ }
}
@@ -743,14 +728,15 @@ class ControlFlowGraphBuilder {
popAndAddEdge(node)
val whenExitNode = whenExitNodes.top()
addEdge(node, whenExitNode, propagateDeadness = false)
levelCounter -= whenBranchIndices.top().getValue(whenBranch)
levelCounter++
return node
}
fun exitWhenExpression(
whenExpression: FirWhenExpression,
callCompleted: Boolean
): Triple<WhenExitNode, WhenSyntheticElseBranchNode?, MergePostponedLambdaExitsNode?> {
): Pair<WhenExitNode, WhenSyntheticElseBranchNode?> {
levelCounter -= whenExpression.branches.size
val whenExitNode = whenExitNodes.pop()
// exit from last condition node still on stack
// we should remove it
@@ -762,11 +748,11 @@ class ControlFlowGraphBuilder {
addEdge(this, whenExitNode)
}
} else null
mergeDataFlowFromPostponedLambdas(whenExitNode, callCompleted)
whenExitNode.updateDeadStatus()
lastNodes.push(whenExitNode)
levelCounter--
whenBranchIndices.pop()
return Triple(whenExitNode, syntheticElseBranchNode, mergeDataFlowFromPostponedLambdas(whenExitNode, callCompleted))
return whenExitNode to syntheticElseBranchNode
}
// ----------------------------------- While Loop -----------------------------------
@@ -1015,7 +1001,7 @@ class ControlFlowGraphBuilder {
}
}
fun exitTryExpression(callCompleted: Boolean): Pair<TryExpressionExitNode, MergePostponedLambdaExitsNode?> {
fun exitTryExpression(callCompleted: Boolean): TryExpressionExitNode {
levelCounter--
catchNodeStorages.pop()
val catchExitNodes = catchExitNodeStorages.pop()
@@ -1024,6 +1010,7 @@ class ControlFlowGraphBuilder {
notCompletedFunctionCalls.pop().forEach(::completeFunctionCall)
val node = tryExitNodes.pop()
mergeDataFlowFromPostponedLambdas(node, callCompleted)
node.updateDeadStatus()
lastNodes.push(node)
@@ -1038,7 +1025,7 @@ class ControlFlowGraphBuilder {
lastNodes.push(stub)
}
return node to mergeDataFlowFromPostponedLambdas(node, callCompleted)
return node
}
//this is a workaround to make function call dead when call is completed _after_ building its node in the graph
@@ -1245,18 +1232,18 @@ class ControlFlowGraphBuilder {
return enterNode
}
fun exitSafeCall(): Pair<ExitSafeCallNode, MergePostponedLambdaExitsNode?> {
fun exitSafeCall(): ExitSafeCallNode {
// There will be two paths towards this exit safe call node:
// one from the node prior to the enclosing safe call, and
// the other from the selector part in the enclosing safe call.
// Note that *neither* points to the safe call directly.
// So, when it comes to the real exit of the enclosing block/function,
// the safe call bound to this exit safe call node should be retrieved.
return exitSafeCallNodes.pop().let {
return exitSafeCallNodes.pop().also {
addNewSimpleNode(it)
it.updateDeadStatus()
// Safe calls only have one user-specified branch, so if any lambdas were postponed, they still are.
it to mergeDataFlowFromPostponedLambdas(it, callCompleted = false)
mergeDataFlowFromPostponedLambdas(it, callCompleted = false)
it.updateDeadStatus()
}
}
@@ -1291,11 +1278,12 @@ class ControlFlowGraphBuilder {
return Triple(lhsExitNode, lhsIsNotNullNode, rhsEnterNode)
}
fun exitElvis(lhsIsNotNull: Boolean, callCompleted: Boolean): Pair<ElvisExitNode, MergePostponedLambdaExitsNode?> {
fun exitElvis(lhsIsNotNull: Boolean, callCompleted: Boolean): ElvisExitNode {
val exitNode = exitElvisExpressionNodes.pop()
addNewSimpleNode(exitNode, isDead = lhsIsNotNull)
mergeDataFlowFromPostponedLambdas(exitNode, callCompleted)
exitNode.updateDeadStatus()
return exitNode to mergeDataFlowFromPostponedLambdas(exitNode, callCompleted)
return exitNode
}
// ----------------------------------- Contract description -----------------------------------
@@ -1318,7 +1306,7 @@ class ControlFlowGraphBuilder {
// -------------------------------------------------------------------------------------------------------------------------
fun reset() {
dataFlowSourcesForNextCompletedCall.reset()
postponedLambdaExits.reset()
lastNodes.reset()
}
@@ -223,7 +223,7 @@ fun ControlFlowGraphBuilder.createEnterSafeCallNode(fir: FirSafeCallExpression):
fun ControlFlowGraphBuilder.createPostponedLambdaExitNode(fir: FirAnonymousFunctionExpression): PostponedLambdaExitNode =
PostponedLambdaExitNode(currentGraph, fir, levelCounter, createId())
fun ControlFlowGraphBuilder.createPostponedLambdaEnterNode(fir: FirAnonymousFunction): PostponedLambdaEnterNode =
fun ControlFlowGraphBuilder.createPostponedLambdaEnterNode(fir: FirAnonymousFunctionExpression): PostponedLambdaEnterNode =
PostponedLambdaEnterNode(currentGraph, fir, levelCounter, createId())
fun ControlFlowGraphBuilder.createAnonymousFunctionExpressionExitNode(fir: FirAnonymousFunctionExpression): AnonymousFunctionExpressionExitNode =
@@ -129,7 +129,10 @@ sealed class CFGNode<out E : FirElement>(val owner: ControlFlowGraph, val level:
open var flow: PersistentFlow
get() = _flow ?: throw IllegalStateException("flow for $this not initialized - traversing nodes in wrong order?")
@CfgInternals
set(value) { _flow = value } // TODO: forbid reassignment
set(value) {
assert(_flow == null) { "reassigning flow for $this" }
_flow = value
}
@CfgInternals
fun updateDeadStatus() {
@@ -240,7 +243,7 @@ class ExitDefaultArgumentsNode(owner: ControlFlowGraph, override val fir: FirVal
// ----------------------------------- Anonymous function -----------------------------------
class PostponedLambdaEnterNode(owner: ControlFlowGraph, override val fir: FirAnonymousFunction, level: Int, id: Int) : CFGNodeWithSubgraphs<FirAnonymousFunction>(owner, level, id) {
class PostponedLambdaEnterNode(owner: ControlFlowGraph, override val fir: FirAnonymousFunctionExpression, level: Int, id: Int) : CFGNodeWithSubgraphs<FirAnonymousFunctionExpression>(owner, level, id) {
override fun <R, D> accept(visitor: ControlFlowGraphVisitor<R, D>, data: D): R {
return visitor.visitPostponedLambdaEnterNode(this, data)
}
+6 -6
View File
@@ -712,7 +712,7 @@ digraph kt44814_kt {
188 -> {189};
189 -> {190};
190 -> {191};
191 -> {192 238};
191 -> {192 238 193};
191 -> {238} [style=dashed];
192 -> {193};
192 -> {191} [color=green style=dashed];
@@ -738,10 +738,11 @@ digraph kt44814_kt {
211 -> {212};
212 -> {217 213};
213 -> {214};
214 -> {232};
214 -> {215} [color=red];
214 -> {232 216};
214 -> {215} [style=dotted];
214 -> {232} [style=dashed];
215 -> {216};
215 -> {221} [color=red];
215 -> {216} [color=green];
216 -> {218};
217 -> {218};
218 -> {221 219};
@@ -763,8 +764,7 @@ digraph kt44814_kt {
234 -> {235};
235 -> {236};
236 -> {237};
237 -> {221} [color=red];
237 -> {215} [color=green];
237 -> {215};
238 -> {239};
239 -> {240};
240 -> {241 243};