Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.

Commit 20ee98a

Browse files
authored
Merge pull request #3841 from dkorpel/remove-old-mctor-cycle
Remove `--DRT-oncycle=deprecate` option
2 parents 8f12ffe + 1bf4c7c commit 20ee98a

File tree

3 files changed

+10
-199
lines changed

3 files changed

+10
-199
lines changed

changelog/drt-oncycle-deprecate.dd

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
`--DRT-oncycle=deprecate` is removed
2+
3+
The option was [introduced in 2.072.2](https://dlang.org/changelog/2.072.2.html#drt-cycle-deprecated) to help transition code that relied on the old faulty cycle checker for module constructors.
4+
It now prints a warning and does the same as the default, `--DRT-oncycle=abort`.
5+
See also: $(DDSUBLINK spec/module, order_of_static_ctor, Order of Static Construction) in the specification.

src/rt/minfo.d

Lines changed: 3 additions & 197 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,6 @@ struct ModuleGroup
169169

170170
enum OnCycle
171171
{
172-
deprecate,
173172
abort,
174173
print,
175174
ignore
@@ -180,7 +179,9 @@ struct ModuleGroup
180179
switch (cycleHandling) with(OnCycle)
181180
{
182181
case "deprecate":
183-
onCycle = deprecate;
182+
import core.stdc.stdio : fprintf, stderr;
183+
// Option deprecated in 2.101, remove in 2.111
184+
fprintf(stderr, "`--DRT-oncycle=deprecate` is no longer supported, using `abort` instead\n");
184185
break;
185186
case "abort":
186187
onCycle = abort;
@@ -356,14 +357,6 @@ struct ModuleGroup
356357
// was already started, this is a cycle.
357358
final switch (onCycle) with(OnCycle)
358359
{
359-
case deprecate:
360-
// check with old algorithm
361-
if (sortCtorsOld(edges))
362-
{
363-
// unwind to print deprecation message.
364-
return false; // deprecated cycle error
365-
}
366-
goto case abort; // fall through
367360
case abort:
368361

369362
string errmsg = "";
@@ -533,193 +526,6 @@ struct ModuleGroup
533526
sortCtors(rt_configOption("oncycle"));
534527
}
535528

536-
/******************************
537-
* This is the old ctor sorting algorithm that does not find all cycles.
538-
*
539-
* It is here to allow the deprecated behavior from the original algorithm
540-
* until people have fixed their code.
541-
*
542-
* If no cycles are found, the _ctors and _tlsctors are replaced with the
543-
* ones generated by this algorithm to preserve the old incorrect ordering
544-
* behavior.
545-
*
546-
* Params:
547-
* edges = The module edges as found in the `importedModules` member of
548-
* each ModuleInfo. Generated in sortCtors.
549-
* Returns:
550-
* true if no cycle is found, false if one was.
551-
*/
552-
bool sortCtorsOld(int[][] edges)
553-
{
554-
immutable len = edges.length;
555-
assert(len == _modules.length);
556-
557-
static struct StackRec
558-
{
559-
@property int mod()
560-
{
561-
return _mods[_idx];
562-
}
563-
564-
int[] _mods;
565-
size_t _idx;
566-
}
567-
568-
auto stack = (cast(StackRec*).calloc(len, StackRec.sizeof))[0 .. len];
569-
// TODO: reuse GCBits by moving it to core.internal.container
570-
immutable nwords = (len + 8 * size_t.sizeof - 1) / (8 * size_t.sizeof);
571-
auto ctorstart = cast(size_t*).malloc(nwords * size_t.sizeof);
572-
auto ctordone = cast(size_t*).malloc(nwords * size_t.sizeof);
573-
int[] initialEdges = (cast(int *)malloc(int.sizeof * len))[0 .. len];
574-
if (!stack.ptr || ctorstart is null || ctordone is null || !initialEdges.ptr)
575-
assert(0);
576-
scope (exit)
577-
{
578-
.free(stack.ptr);
579-
.free(ctorstart);
580-
.free(ctordone);
581-
.free(initialEdges.ptr);
582-
}
583-
584-
// initialize the initial edges
585-
foreach (i, ref v; initialEdges)
586-
v = cast(int)i;
587-
588-
bool sort(ref immutable(ModuleInfo)*[] ctors, uint mask)
589-
{
590-
import core.bitop;
591-
592-
ctors = (cast(immutable(ModuleInfo)**).malloc(len * size_t.sizeof))[0 .. len];
593-
if (!ctors.ptr)
594-
assert(0);
595-
596-
// clean flags
597-
memset(ctorstart, 0, nwords * size_t.sizeof);
598-
memset(ctordone, 0, nwords * size_t.sizeof);
599-
size_t stackidx = 0;
600-
size_t cidx;
601-
602-
int[] mods = initialEdges;
603-
604-
size_t idx;
605-
while (true)
606-
{
607-
while (idx < mods.length)
608-
{
609-
auto m = mods[idx];
610-
611-
if (bt(ctordone, m))
612-
{
613-
// this module has already been processed, skip
614-
++idx;
615-
continue;
616-
}
617-
else if (bt(ctorstart, m))
618-
{
619-
/* Trace back to the begin of the cycle.
620-
*/
621-
bool ctorInCycle;
622-
size_t start = stackidx;
623-
while (start--)
624-
{
625-
auto sm = stack[start].mod;
626-
if (sm == m)
627-
break;
628-
assert(sm >= 0);
629-
if (bt(ctorstart, sm))
630-
ctorInCycle = true;
631-
}
632-
assert(stack[start].mod == m);
633-
if (ctorInCycle)
634-
{
635-
return false;
636-
}
637-
else
638-
{
639-
/* This is also a cycle, but the import chain does not constrain
640-
* the order of initialization, either because the imported
641-
* modules have no ctors or the ctors are standalone.
642-
*/
643-
++idx;
644-
}
645-
}
646-
else
647-
{
648-
auto curmod = _modules[m];
649-
if (curmod.flags & mask)
650-
{
651-
if (curmod.flags & MIstandalone || !edges[m].length)
652-
{ // trivial ctor => sort in
653-
ctors[cidx++] = curmod;
654-
bts(ctordone, m);
655-
}
656-
else
657-
{ // non-trivial ctor => defer
658-
bts(ctorstart, m);
659-
}
660-
}
661-
else // no ctor => mark as visited
662-
{
663-
bts(ctordone, m);
664-
}
665-
666-
if (edges[m].length)
667-
{
668-
/* Internal runtime error, recursion exceeds number of modules.
669-
*/
670-
(stackidx < len) || assert(0);
671-
672-
// recurse
673-
stack[stackidx++] = StackRec(mods, idx);
674-
idx = 0;
675-
mods = edges[m];
676-
}
677-
}
678-
}
679-
680-
if (stackidx)
681-
{ // pop old value from stack
682-
--stackidx;
683-
mods = stack[stackidx]._mods;
684-
idx = stack[stackidx]._idx;
685-
auto m = mods[idx++];
686-
if (bt(ctorstart, m) && !bts(ctordone, m))
687-
ctors[cidx++] = _modules[m];
688-
}
689-
else // done
690-
break;
691-
}
692-
// store final number and shrink array
693-
ctors = (cast(immutable(ModuleInfo)**).realloc(ctors.ptr, cidx * size_t.sizeof))[0 .. cidx];
694-
return true;
695-
}
696-
697-
/* Do two passes: ctor/dtor, tlsctor/tlsdtor
698-
*/
699-
immutable(ModuleInfo)*[] _ctors2;
700-
immutable(ModuleInfo)*[] _tlsctors2;
701-
auto result = sort(_ctors2, MIctor | MIdtor) && sort(_tlsctors2, MItlsctor | MItlsdtor);
702-
if (result) // no cycle
703-
{
704-
// fall back to original ordering as part of the deprecation.
705-
if (_ctors.ptr)
706-
.free(_ctors.ptr);
707-
_ctors = _ctors2;
708-
if (_tlsctors.ptr)
709-
.free(_tlsctors.ptr);
710-
_tlsctors = _tlsctors2;
711-
}
712-
else
713-
{
714-
// free any allocated memory that will be forgotten
715-
if (_ctors2.ptr)
716-
.free(_ctors2.ptr);
717-
if (_tlsctors2.ptr)
718-
.free(_tlsctors2.ptr);
719-
}
720-
return result;
721-
}
722-
723529
void runCtors()
724530
{
725531
// run independent ctors

test/cycles/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ $(ROOT)/cycle_abort.done: RETCODE=1
1414
$(ROOT)/cycle_abort.done: LINES=7
1515
$(ROOT)/cycle_print.done: RETCODE=0
1616
$(ROOT)/cycle_print.done: LINES=6
17-
$(ROOT)/cycle_deprecate.done: RETCODE=0
18-
$(ROOT)/cycle_deprecate.done: LINES=4
17+
$(ROOT)/cycle_deprecate.done: RETCODE=1
18+
$(ROOT)/cycle_deprecate.done: LINES=8
1919
$(ROOT)/%.done: $(ROOT)/test_cycles
2020
@echo Testing $*
2121
$(QUIET)$(TIMELIMIT)$(ROOT)/test_cycles --DRT-oncycle=$(patsubst cycle_%.done,%, $(notdir $@)) > $@ 2>&1; test $$? -eq $(RETCODE)

0 commit comments

Comments
 (0)