this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

internal/core/adt: apply vertex rewriting to blocked tasks

Now we rewrite nodes, this means we can rewrite
ALL waiting tasks. Task are now only added to
the respective queues after they have been
rewritten.

Issue #3967

Signed-off-by: Marcel van Lohuizen <mpvl@gmail.com>
Change-Id: I0081496389fef3271a161d24832c709f5cf40285
Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1217086
Reviewed-by: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: CUEcueckoo <cueckoo@cuelang.org>

+79 -198
+53 -173
cue/testdata/eval/disjunctioncross.txtar
··· 103 103 } 104 104 } 105 105 -- out/evalalpha/stats -- 106 - Leaks: 282 106 + Leaks: 291 107 107 Freed: 0 108 108 Reused: 0 109 - Allocs: 282 109 + Allocs: 291 110 110 Retain: 0 111 111 112 - Unifications: 162 113 - Conjuncts: 364 114 - Disjuncts: 68 112 + Unifications: 165 113 + Conjuncts: 379 114 + Disjuncts: 74 115 115 116 - CloseIDElems: 1555 117 - NumCloseIDs: 88 116 + CloseIDElems: 1476 117 + NumCloseIDs: 91 118 118 -- diff/-out/evalalpha/stats<==>+out/eval/stats -- 119 119 diff old new 120 120 --- old ··· 132 132 - 133 133 -CloseIDElems: 0 134 134 -NumCloseIDs: 8 135 - +Leaks: 282 135 + +Leaks: 291 136 136 +Freed: 0 137 137 +Reused: 0 138 - +Allocs: 282 138 + +Allocs: 291 139 139 +Retain: 0 140 140 + 141 - +Unifications: 162 142 - +Conjuncts: 364 143 - +Disjuncts: 68 141 + +Unifications: 165 142 + +Conjuncts: 379 143 + +Disjuncts: 74 144 144 + 145 - +CloseIDElems: 1555 146 - +NumCloseIDs: 88 145 + +CloseIDElems: 1476 146 + +NumCloseIDs: 91 147 147 -- out/eval/stats -- 148 148 Leaks: 16 149 149 Freed: 292 ··· 205 205 }) } 206 206 } 207 207 #Application: (#struct){ 208 - oneOrTwo: (#struct){ |(*(#struct){ 208 + oneOrTwo: (#struct){ |((#struct){ 209 209 kind: (string){ "one" } 210 210 one: (#struct){ 211 211 oneField: (string){ "value" } 212 212 } 213 - }, *(#struct){ 213 + }, (#struct){ 214 214 kind: (string){ "two" } 215 215 two: (#struct){ 216 216 optional?: (string){ string } ··· 234 234 } 235 235 #Application: (#struct){ 236 236 oneOrTwo: (#struct){ |(*(#struct){ 237 + kind: (string){ "two" } 238 + two: (#struct){ 239 + optional: (string){ |(*(string){ "optional set" }, (string){ string }) } 240 + } 241 + }, (#struct){ 237 242 kind: (string){ "one" } 238 243 one: (#struct){ 239 244 oneField: (string){ "value" } 240 245 } 241 - }, *(#struct){ 246 + }, (#struct){ 242 247 kind: (string){ "two" } 243 248 two: (#struct){ 244 249 optional?: (string){ string } ··· 258 263 } 259 264 } 260 265 #Application: (#struct){ 261 - oneOrTwo: (#struct){ |(*(#struct){ 266 + oneOrTwo: (#struct){ |((#struct){ 262 267 kind: (string){ "one" } 263 268 one: (#struct){ 264 269 oneField: (string){ "value" } 265 270 } 266 - }, *(#struct){ 271 + }, (#struct){ 267 272 kind: (string){ "two" } 268 273 two: (#struct){ 269 274 optional?: (string){ string } ··· 273 278 } 274 279 local: (struct){ 275 280 out: (#struct){ 276 - oneOrTwo: (#struct){ 277 - two: (#struct){ 278 - optional?: (string){ string } 279 - } 280 - kind: (string){ "two" } 281 - } 281 + oneOrTwo: (#struct){ |(*(#struct){ 282 + two: (#struct){ 283 + optional: (string){ |(*(string){ "optional set" }, (string){ string }) } 284 + } 285 + kind: (string){ "two" } 286 + }, (#struct){ 287 + two: (#struct){ 288 + optional?: (string){ string } 289 + } 290 + kind: (string){ "two" } 291 + }) } 282 292 } 283 293 #Application: (#struct){ 284 294 oneOrTwo: (#struct){ |(*(#struct){ 295 + kind: (string){ "two" } 296 + two: (#struct){ 297 + optional: (string){ |(*(string){ "optional set" }, (string){ string }) } 298 + } 299 + }, (#struct){ 285 300 kind: (string){ "one" } 286 301 one: (#struct){ 287 302 oneField: (string){ "value" } 288 303 } 289 - }, *(#struct){ 304 + }, (#struct){ 290 305 kind: (string){ "two" } 291 306 two: (#struct){ 292 307 optional?: (string){ string } ··· 350 365 diff old new 351 366 --- old 352 367 +++ new 353 - @@ -46,49 +46,39 @@ 368 + @@ -45,12 +45,7 @@ 369 + }) } 354 370 } 355 371 #Application: (#struct){ 356 - oneOrTwo: (#struct){ |(*(#struct){ 357 - - kind: (string){ "two" } 358 - - two: (#struct){ 359 - - optional: (string){ |(*(string){ "optional set" }, (string){ string }) } 360 - - } 361 - - }, (#struct){ 362 - - kind: (string){ "one" } 363 - - one: (#struct){ 364 - - oneField: (string){ "value" } 365 - - } 366 - - }, (#struct){ 367 - - kind: (string){ "two" } 368 - - two: (#struct){ 369 - - optional?: (string){ string } 370 - - } 371 - - }) } 372 - - } 373 - - } 374 - - local: (struct){ 375 - - out: (#struct){ 376 372 - oneOrTwo: (#struct){ |(*(#struct){ 377 373 - kind: (string){ "two" } 378 374 - two: (#struct){ 379 375 - optional: (string){ |(*(string){ "optional set" }, (string){ string }) } 380 376 - } 381 377 - }, (#struct){ 382 - - kind: (string){ "two" } 383 - - two: (#struct){ 384 - - optional?: (string){ string } 385 - - } 386 - - }) } 387 - - } 388 - - #Application: (#struct){ 389 - - oneOrTwo: (#struct){ |(*(#struct){ 390 - - kind: (string){ "two" } 391 - - two: (#struct){ 392 - - optional: (string){ |(*(string){ "optional set" }, (string){ string }) } 393 - - } 394 - - }, (#struct){ 395 - - kind: (string){ "one" } 396 - - one: (#struct){ 397 - - oneField: (string){ "value" } 398 - - } 399 - - }, (#struct){ 400 - + kind: (string){ "one" } 401 - + one: (#struct){ 402 - + oneField: (string){ "value" } 403 - + } 404 - + }, *(#struct){ 405 - + kind: (string){ "two" } 406 - + two: (#struct){ 407 - + optional?: (string){ string } 408 - + } 409 - + }) } 410 - + } 411 - + } 412 - + local: (struct){ 413 - + out: (#struct){ 414 - + oneOrTwo: (#struct){ |(*(#struct){ 415 - + kind: (string){ "two" } 416 - + two: (#struct){ 417 - + optional: (string){ |(*(string){ "optional set" }, (string){ string }) } 418 - + } 419 - + }, (#struct){ 420 - + kind: (string){ "two" } 421 - + two: (#struct){ 422 - + optional?: (string){ string } 423 - + } 424 - + }) } 425 - + } 426 - + #Application: (#struct){ 427 - + oneOrTwo: (#struct){ |(*(#struct){ 428 - + kind: (string){ "one" } 429 - + one: (#struct){ 430 - + oneField: (string){ "value" } 431 - + } 432 - + }, *(#struct){ 433 - kind: (string){ "two" } 434 - two: (#struct){ 435 - optional?: (string){ string } 436 - @@ -100,63 +90,43 @@ 378 + + oneOrTwo: (#struct){ |((#struct){ 379 + kind: (string){ "one" } 380 + one: (#struct){ 381 + oneField: (string){ "value" } 382 + @@ -100,25 +95,15 @@ 437 383 fieldDiscriminator: (struct){ 438 384 crossing: (struct){ 439 385 out: (#struct){ ··· 456 402 - optional: (string){ |(*(string){ "optional set" }, (string){ string }) } 457 403 - } 458 404 - }, (#struct){ 459 - - kind: (string){ "one" } 460 - - one: (#struct){ 461 - - oneField: (string){ "value" } 462 - - } 463 - - }, (#struct){ 464 - - kind: (string){ "two" } 465 - - two: (#struct){ 466 - - optional?: (string){ string } 467 - - } 468 - - }) } 469 - - } 470 - - } 471 - - local: (struct){ 472 - - out: (#struct){ 473 - - oneOrTwo: (#struct){ |(*(#struct){ 474 - - two: (#struct){ 475 - - optional: (string){ |(*(string){ "optional set" }, (string){ string }) } 476 - - } 477 - - kind: (string){ "two" } 478 - - }, (#struct){ 479 - - two: (#struct){ 480 - - optional?: (string){ string } 481 - - } 482 - - kind: (string){ "two" } 483 - - }) } 484 - - } 485 - - #Application: (#struct){ 486 - - oneOrTwo: (#struct){ |(*(#struct){ 487 - - kind: (string){ "two" } 488 - - two: (#struct){ 489 - - optional: (string){ |(*(string){ "optional set" }, (string){ string }) } 490 - - } 491 - - }, (#struct){ 492 - - kind: (string){ "one" } 493 - - one: (#struct){ 494 - - oneField: (string){ "value" } 495 - - } 496 - - }, (#struct){ 497 405 + oneOrTwo: (#struct){ 498 406 + two: (#struct){ 499 407 + optional?: (string){ string } ··· 502 410 + } 503 411 + } 504 412 + #Application: (#struct){ 505 - + oneOrTwo: (#struct){ |(*(#struct){ 506 - + kind: (string){ "one" } 507 - + one: (#struct){ 508 - + oneField: (string){ "value" } 509 - + } 510 - + }, *(#struct){ 511 - + kind: (string){ "two" } 512 - + two: (#struct){ 513 - + optional?: (string){ string } 514 - + } 515 - + }) } 516 - + } 517 - + } 518 - + local: (struct){ 519 - + out: (#struct){ 520 - + oneOrTwo: (#struct){ 521 - + two: (#struct){ 522 - + optional?: (string){ string } 523 - + } 524 - + kind: (string){ "two" } 525 - + } 526 - + } 527 - + #Application: (#struct){ 528 - + oneOrTwo: (#struct){ |(*(#struct){ 529 - + kind: (string){ "one" } 530 - + one: (#struct){ 531 - + oneField: (string){ "value" } 532 - + } 533 - + }, *(#struct){ 534 - kind: (string){ "two" } 535 - two: (#struct){ 536 - optional?: (string){ string } 537 - @@ -168,45 +138,48 @@ 413 + + oneOrTwo: (#struct){ |((#struct){ 414 + kind: (string){ "one" } 415 + one: (#struct){ 416 + oneField: (string){ "value" } 417 + @@ -168,45 +153,48 @@ 538 418 issue3967: (struct){ 539 419 error: (struct){ 540 420 nested: (struct){
+6 -6
internal/core/adt/disjunct2.go
··· 504 504 505 505 n.scheduler.blocking = n.scheduler.blocking[:0] 506 506 507 + // TODO(perf): do not set to nil, but rather maintain an index to unwind 508 + // to avoid allocting new arrays. 509 + saved := n.ctx.blocking 510 + n.ctx.blocking = nil 511 + defer func() { n.ctx.blocking = saved }() 512 + 507 513 d := oc.cloneRoot(n) 508 514 509 515 n.ctx.pushOverlay(n.node, oc.vertexMap) ··· 525 531 d.scheduleConjunct(c, c.CloseInfo) 526 532 527 533 oc.unlinkOverlay() 528 - 529 - // TODO(perf): do not set to nil, but rather maintain an index to unwind 530 - // to avoid allocting new arrays. 531 - saved := n.ctx.blocking 532 - n.ctx.blocking = nil 533 - defer func() { n.ctx.blocking = saved }() 534 534 535 535 d.defaultMode = n.defaultMode 536 536 d.origDefaultMode = m
+20 -19
internal/core/adt/overlay.go
··· 167 167 168 168 for _, t := range n.tasks { 169 169 ctx.rewriteComprehension(t) 170 + 171 + t.node = ctx.vertexMap.deref(t.node.node).state 172 + 173 + if t.blockedOn != nil { 174 + before := t.blockedOn.node.node 175 + after := ctx.vertexMap.deref(before) 176 + // Tasks that are blocked on nodes outside the current scope 177 + // of the disjunction should should be added to blocking queues. 178 + if before == after { 179 + continue 180 + } 181 + s := &after.state.scheduler 182 + t.blockedOn = s 183 + s.blocking = append(s.blocking, t) 184 + s.ctx.blocking = append(s.ctx.blocking, t) 185 + s.needs |= t.blockCondition 186 + } 170 187 } 171 188 } 172 189 ··· 203 220 v := &Vertex{} 204 221 *v = *x 205 222 ctx.vertexMap[x] = v 206 - 207 223 x.overlay = v 208 224 209 225 ctx.vertices = append(ctx.vertices, x) ··· 329 345 for _, t := range ss.tasks { 330 346 switch t.state { 331 347 case taskWAITING: 332 - // Do not unblock previously blocked tasks, unless they are 333 - // associated with this node. 334 - // TODO: an edge case is when a task is blocked on another node 335 - // within the same disjunction. We could solve this by associating 336 - // each nodeContext with a unique ID (like a generation counter) for 337 - // the disjunction. 338 - if t.node != src || t.blockedOn != ss { 339 - break 340 - } 341 348 t.defunct = true 342 349 t := ctx.cloneTask(t, ds, ss) 343 350 ds.tasks = append(ds.tasks, t) 344 - ds.blocking = append(ds.blocking, t) 345 - ctx.ctx.blocking = append(ctx.ctx.blocking, t) 351 + // We add this task to ds.blocking and ctx.ctx.blocking in 352 + // cloneRoot, after its node references have been rewritten. 346 353 347 354 case taskREADY: 348 355 t.defunct = true ··· 378 385 completes: t.completes, 379 386 unblocked: t.unblocked, 380 387 blockCondition: t.blockCondition, 388 + blockedOn: t.blockedOn, // will be rewritten later 381 389 err: t.err, 382 390 env: env, 383 391 x: t.x, ··· 389 397 // known. 390 398 comp: t.comp, 391 399 leaf: t.leaf, 392 - } 393 - 394 - if t.blockedOn != nil { 395 - if t.blockedOn != src { 396 - panic("invalid scheduler") 397 - } 398 - d.blockedOn = dst 399 400 } 400 401 401 402 return d