Skip to content

Commit c2ebfdb

Browse files
committed
internal/core/adt: split closeContext.arcs
Right now, closeContext.arcs is used to store both arcs and notifications. Although they share a lot of the same logic, it is confusing and prone to bugs. It also makes changing either mechanism hard and makes it harder to understand how everything works. This CL does a "dumb" split of the functionality. Further cleaning up can be done down the line. Signed-off-by: Marcel van Lohuizen <[email protected]> Change-Id: Ib73254166e33210192c19b9cc4a3d092ffae1bfc Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1207444 Reviewed-by: Daniel Martí <[email protected]> Unity-Result: CUE porcuepine <[email protected]> TryBot-Result: CUEcueckoo <[email protected]>
1 parent 13f38c9 commit c2ebfdb

File tree

4 files changed

+105
-42
lines changed

4 files changed

+105
-42
lines changed

Diff for: internal/core/adt/disjunct2.go

-6
Original file line numberDiff line numberDiff line change
@@ -737,13 +737,7 @@ func equalPartialNode(ctx *OpContext, x, y *closeContext) bool {
737737
// TODO(perf): use merge sort
738738
outer:
739739
for _, a := range x.arcs {
740-
if a.kind != ARC {
741-
continue outer
742-
}
743740
for _, b := range y.arcs {
744-
if b.kind != ARC {
745-
continue
746-
}
747741
if a.key.src.Label != b.key.src.Label {
748742
continue
749743
}

Diff for: internal/core/adt/fields.go

+78-29
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,15 @@ type closeContext struct {
268268
// tree as this closeContext. In both cases the are keyed by Vertex.
269269
arcs []ccArc
270270

271+
// notify represents closeContexts which to notify of updates.
272+
//
273+
// TODO: Note that this slice is very similar to nodeContext.notify and the
274+
// use of these can likely be merged. It may be better to let the notify
275+
// originate from a more specific closeContext, allowing it to stopped
276+
// sooner and possibly even remove the need for breaking dependency
277+
// cycles.
278+
notify []ccArc
279+
271280
// parentIndex is the position in the parent's arcs slice that corresponds
272281
// to this closeContext. This is currently unused. The intention is to use
273282
// this to allow groups with single elements (which will be the majority)
@@ -315,7 +324,6 @@ func (c *closeContext) updateArcType(ctx *OpContext, t ArcType) {
315324
}
316325

317326
type ccArc struct {
318-
kind depKind
319327
decremented bool
320328
// matched indicates the arc is only added to track the destination of a
321329
// matched pattern and that it is not explicitly defined as a field.
@@ -331,6 +339,7 @@ type ccArc struct {
331339
// closeContext.
332340
type ccArcRef struct {
333341
src *closeContext
342+
kind depKind
334343
index int
335344
}
336345

@@ -464,7 +473,7 @@ func (cc *closeContext) getKeyedCC(ctx *OpContext, key *closeContext, c CycleInf
464473
}
465474

466475
func (cc *closeContext) linkNotify(ctx *OpContext, key *closeContext) bool {
467-
for _, a := range cc.arcs {
476+
for _, a := range cc.notify {
468477
if a.key == key {
469478
return false
470479
}
@@ -556,33 +565,67 @@ func (c *closeContext) addDependency(ctx *OpContext, kind depKind, matched bool,
556565
// NOTE: do not increment
557566
// - either root closeContext or otherwise resulting from sub closeContext
558567
// all conjuncts will be added now, notified, or scheduled as task.
568+
switch kind {
569+
case ARC:
570+
for _, a := range c.arcs {
571+
if a.key == key {
572+
panic("addArc: Label already exists")
573+
}
574+
}
575+
child.incDependent(ctx, kind, c) // matched in decDependent REF(arcs)
576+
577+
c.arcs = append(c.arcs, ccArc{
578+
matched: matched,
579+
key: key,
580+
cc: child,
581+
})
582+
583+
// TODO: this tests seems sensible, but panics. Investigate what could
584+
// trigger this.
585+
// if child.src.Parent != c.src {
586+
// panic("addArc: inconsistent parent")
587+
// }
588+
if child.src.cc() != root.src.cc() {
589+
panic("addArc: inconsistent root")
590+
}
559591

560-
child.incDependent(ctx, kind, c) // matched in decDependent REF(arcs)
561-
562-
for _, a := range c.arcs {
563-
if a.key == key {
564-
panic("addArc: Label already exists")
592+
root.externalDeps = append(root.externalDeps, ccArcRef{
593+
src: c,
594+
kind: kind,
595+
index: len(c.arcs) - 1,
596+
})
597+
case NOTIFY:
598+
for _, a := range c.notify {
599+
if a.key == key {
600+
panic("addArc: Label already exists")
601+
}
602+
}
603+
child.incDependent(ctx, kind, c) // matched in decDependent REF(arcs)
604+
605+
c.notify = append(c.notify, ccArc{
606+
matched: matched,
607+
key: key,
608+
cc: child,
609+
})
610+
611+
// TODO: this tests seems sensible, but panics. Investigate what could
612+
// trigger this.
613+
// if child.src.Parent != c.src {
614+
// panic("addArc: inconsistent parent")
615+
// }
616+
if child.src.cc() != root.src.cc() {
617+
panic("addArc: inconsistent root")
565618
}
619+
620+
root.externalDeps = append(root.externalDeps, ccArcRef{
621+
src: c,
622+
kind: kind,
623+
index: len(c.notify) - 1,
624+
})
625+
default:
626+
panic(kind)
566627
}
567628

568-
// TODO: this tests seems sensible, but panics. Investigate what could
569-
// trigger this.
570-
// if child.src.Parent != c.src {
571-
// panic("addArc: inconsistent parent")
572-
// }
573-
if child.src.cc() != root.src.cc() {
574-
panic("addArc: inconsistent root")
575-
}
576-
c.arcs = append(c.arcs, ccArc{
577-
kind: kind,
578-
matched: matched,
579-
key: key,
580-
cc: child,
581-
})
582-
root.externalDeps = append(root.externalDeps, ccArcRef{
583-
src: c,
584-
index: len(c.arcs) - 1,
585-
})
586629
}
587630

588631
// incDependent needs to be called for any conjunct or child closeContext
@@ -650,7 +693,16 @@ func (c *closeContext) decDependent(ctx *OpContext, kind depKind, dependant *clo
650693
continue
651694
}
652695
c.arcs[i].decremented = true
653-
cc.decDependent(ctx, a.kind, c) // REF(arcs)
696+
cc.decDependent(ctx, ARC, c)
697+
}
698+
699+
for i, a := range c.notify {
700+
cc := a.cc
701+
if a.decremented {
702+
continue
703+
}
704+
c.notify[i].decremented = true
705+
cc.decDependent(ctx, NOTIFY, c)
654706
}
655707

656708
c.finalizePattern()
@@ -1015,9 +1067,6 @@ func isTotal(p Value) bool {
10151067
// this is not the case.
10161068
func injectClosed(ctx *OpContext, closed, dst *closeContext) {
10171069
for _, a := range dst.arcs {
1018-
if a.kind != ARC {
1019-
continue
1020-
}
10211070
ca := a.cc
10221071
switch f := ca.Label(); {
10231072
case ca.src.ArcType == ArcOptional,

Diff for: internal/core/adt/overlay.go

+14-3
Original file line numberDiff line numberDiff line change
@@ -318,9 +318,7 @@ func (ctx *overlayContext) allocCC(cc *closeContext) *closeContext {
318318
// We only explicitly tag dependencies of type ARC. Notifications that
319319
// point within the disjunct overlay will be tagged elsewhere.
320320
for _, a := range cc.arcs {
321-
if a.kind == ARC {
322-
ctx.allocCC(a.cc)
323-
}
321+
ctx.allocCC(a.cc)
324322
}
325323

326324
return o
@@ -450,6 +448,19 @@ func (ctx *overlayContext) initCloneCC(x *closeContext) {
450448
o.arcs = append(o.arcs, a)
451449
}
452450

451+
for _, a := range x.notify {
452+
// If an arc does not have an overlay, we should not decrement the
453+
// dependency counter. We simply remove the dependency in that case.
454+
if a.cc.overlay == nil {
455+
continue
456+
}
457+
if a.key.overlay != nil {
458+
a.key = a.key.overlay // TODO: is this necessary?
459+
}
460+
a.cc = a.cc.overlay
461+
o.notify = append(o.notify, a)
462+
}
463+
453464
// NOTE: copying externalDeps is hard and seems unnecessary, as it needs to
454465
// be resolved in the base anyway.
455466
}

Diff for: internal/core/adt/unify.go

+13-4
Original file line numberDiff line numberDiff line change
@@ -487,9 +487,12 @@ func (n *nodeContext) completeNodeTasks(mode runMode) {
487487
// TODO: replace with something more principled that does not piggyback on
488488
// debug information.
489489
for _, r := range v.cc().externalDeps {
490+
if r.kind != NOTIFY {
491+
continue
492+
}
490493
src := r.src
491-
a := &src.arcs[r.index]
492-
if a.decremented || a.kind != NOTIFY {
494+
a := &src.notify[r.index]
495+
if a.decremented {
493496
continue
494497
}
495498
if n := src.src.getState(n.ctx); n != nil {
@@ -556,14 +559,20 @@ func (n *nodeContext) completeAllArcs(needs condition, mode runMode) bool {
556559
if src.src.IsDisjunct {
557560
continue
558561
}
559-
a := &src.arcs[r.index]
562+
var a *ccArc
563+
switch r.kind {
564+
case ARC:
565+
a = &src.arcs[r.index]
566+
case NOTIFY:
567+
a = &src.notify[r.index]
568+
}
560569
if a.decremented {
561570
continue
562571
}
563572
a.decremented = true
564573

565574
src.src.unify(n.ctx, needTasksDone, attemptOnly)
566-
a.cc.decDependent(n.ctx, a.kind, src) // REF(arcs)
575+
a.cc.decDependent(n.ctx, r.kind, src)
567576
}
568577

569578
n.incDepth()

0 commit comments

Comments
 (0)