35
35
MInew = 0x80000000 // it's the "new" layout
36
36
}
37
37
38
- // Windows: this gets initialized by minit.asm
39
- // Posix: this gets initialized in rt_moduleCtor()
40
- extern (C ) __gshared ModuleInfo * [] _moduleinfo_array;
41
- extern (C ) void _minit();
42
-
43
- struct SortedCtors
38
+ struct ModuleGroup
44
39
{
45
- void alloc (size_t n)
40
+ this (ModuleInfo * [] modules)
41
+ {
42
+ _modules = modules;
43
+ }
44
+
45
+ @property inout (ModuleInfo * )[] modules() inout
46
+ {
47
+ return _modules;
48
+ }
49
+
50
+ void sortCtors ()
46
51
{
47
52
// don't bother to initialize, as they are getting overwritten anyhow
53
+ immutable n = _modules.length;
48
54
_ctors = (cast (ModuleInfo ** ).malloc(n * size_t .sizeof))[0 .. n];
49
55
_tlsctors = (cast (ModuleInfo ** ).malloc(n * size_t .sizeof))[0 .. n];
56
+ .sortCtors(this );
57
+ }
58
+
59
+ void runCtors ()
60
+ {
61
+ // run independent ctors
62
+ runModuleFuncs! (m => m.ictor)(_modules);
63
+ // sorted module ctors
64
+ runModuleFuncs! (m => m.ctor)(_ctors);
65
+ // flag all modules as initialized
66
+ foreach (m; _modules)
67
+ m.flags = m.flags | MIctordone;
68
+ }
69
+
70
+ void runTlsCtors ()
71
+ {
72
+ runModuleFuncs! (m => m.tlsctor)(_tlsctors);
73
+ }
74
+
75
+ void runTlsDtors ()
76
+ {
77
+ runModuleFuncsRev! (m => m.tlsdtor)(_tlsctors);
78
+ }
79
+
80
+ void runDtors ()
81
+ {
82
+ runModuleFuncsRev! (m => m.dtor)(_ctors);
83
+ // clean all initialized flags
84
+ foreach (m; _modules)
85
+ m.flags = m.flags & ~ MIctordone;
86
+
87
+ free();
50
88
}
51
89
52
90
void free ()
@@ -55,13 +93,24 @@ struct SortedCtors
55
93
_ctors = null ;
56
94
.free(_tlsctors.ptr);
57
95
_tlsctors = null ;
96
+ _modules = null ;
58
97
}
59
98
60
- ModuleInfo * [] _ctors;
99
+ private :
100
+ ModuleInfo * [] _modules;
101
+ ModuleInfo * [] _ctors;
61
102
ModuleInfo * [] _tlsctors;
62
103
}
63
104
64
- __gshared SortedCtors _sortedCtors;
105
+ version (Windows )
106
+ {
107
+ // Windows: this gets initialized by minit.asm
108
+ // Posix: this gets initialized in _moduleCtor()
109
+ extern (C ) __gshared ModuleInfo * [] _moduleinfo_array;
110
+ extern (C ) void _minit();
111
+ }
112
+
113
+ __gshared ModuleGroup _moduleGroup;
65
114
66
115
/* *******************************************
67
116
* Iterate over all module infos.
@@ -71,7 +120,7 @@ int moduleinfos_apply(scope int delegate(ref ModuleInfo*) dg)
71
120
{
72
121
int ret = 0 ;
73
122
74
- foreach (m; _moduleinfo_array )
123
+ foreach (m; _moduleGroup._modules )
75
124
{
76
125
// TODO: Should null ModuleInfo be allowed?
77
126
if (m ! is null )
@@ -90,40 +139,27 @@ int moduleinfos_apply(scope int delegate(ref ModuleInfo*) dg)
90
139
91
140
extern (C ) void rt_moduleCtor()
92
141
{
93
- _moduleinfo_array = getModuleInfos();
94
- _sortedCtors = sortCtors(_moduleinfo_array);
95
-
96
- // run independent ctors
97
- runModuleFuncs! ((a) { return a.ictor; })(_moduleinfo_array);
98
- // sorted module ctors
99
- runModuleFuncs! ((a) { return a.ctor; })(_sortedCtors._ctors);
100
- // flag all modules as initialized
101
- foreach (m; _moduleinfo_array)
102
- m.flags = m.flags | MIctordone;
142
+ _moduleGroup = ModuleGroup(getModuleInfos());
143
+ _moduleGroup.sortCtors();
144
+ _moduleGroup.runCtors();
103
145
}
104
146
105
147
extern (C ) void rt_moduleTlsCtor()
106
148
{
107
- runModuleFuncs ! ((a) { return a.tlsctor; })(_sortedCtors._tlsctors );
149
+ _moduleGroup.runTlsCtors( );
108
150
}
109
151
110
152
extern (C ) void rt_moduleTlsDtor()
111
153
{
112
- runModuleFuncsRev ! ((a) { return a.tlsdtor; })(_sortedCtors._tlsctors );
154
+ _moduleGroup.runTlsDtors( );
113
155
}
114
156
115
157
extern (C ) void rt_moduleDtor()
116
158
{
117
- runModuleFuncsRev! ((a) { return a.dtor; })(_sortedCtors._ctors);
118
-
119
- // clean all initialized flags
120
- foreach (m; _moduleinfo_array)
121
- m.flags = m.flags & ~ MIctordone;
122
-
123
- _sortedCtors.free();
159
+ _moduleGroup.runDtors();
124
160
version (Posix )
125
- .free(_moduleinfo_array .ptr);
126
- _moduleinfo_array = null ;
161
+ .free(_moduleGroup._modules .ptr);
162
+ _moduleGroup.free() ;
127
163
}
128
164
129
165
/* *******************************************
@@ -224,29 +260,35 @@ void runModuleFuncsRev(alias getfp)(ModuleInfo*[] modules)
224
260
* constructors.
225
261
*/
226
262
227
- SortedCtors sortCtors (ModuleInfo * [] modules)
263
+ void sortCtors (ref ModuleGroup mgroup)
264
+ in
265
+ {
266
+ assert (mgroup._modules.length == mgroup._ctors.length);
267
+ assert (mgroup._modules.length == mgroup._tlsctors.length);
268
+ }
269
+ body
228
270
{
229
271
enum AllocaLimit = 100 * 1024 ; // 100KB
230
272
231
- immutable size = modules.length * StackRec.sizeof;
273
+ immutable len = mgroup._modules.length;
274
+ immutable size = len * StackRec.sizeof;
232
275
233
- if (! size )
276
+ if (! len )
234
277
{
235
- return SortedCtors.init ;
278
+ return ;
236
279
}
237
280
else if (size <= AllocaLimit)
238
281
{
239
282
auto p = cast (ubyte * ).alloca(size);
240
283
p[0 .. size] = 0 ;
241
- return sortCtorsImpl (modules , (cast (StackRec* )p)[0 .. modules.length ]);
284
+ sortCtorsImpl(mgroup , (cast (StackRec* )p)[0 .. len ]);
242
285
}
243
286
else
244
287
{
245
288
auto p = cast (ubyte * ).malloc(size);
246
289
p[0 .. size] = 0 ;
247
- auto result = sortCtorsImpl(modules , (cast (StackRec* )p)[0 .. modules.length ]);
290
+ sortCtorsImpl(mgroup , (cast (StackRec* )p)[0 .. len ]);
248
291
.free(p);
249
- return result;
250
292
}
251
293
}
252
294
@@ -297,21 +339,18 @@ void onCycleError(StackRec[] stack)
297
339
throw new Exception (" Aborting!" );
298
340
}
299
341
300
- private SortedCtors sortCtorsImpl (ModuleInfo * [] modules , StackRec[] stack)
342
+ private void sortCtorsImpl (ref ModuleGroup mgroup , StackRec[] stack)
301
343
{
302
- SortedCtors result;
303
- result.alloc(modules.length);
304
-
305
344
size_t stackidx;
306
345
bool tlsPass;
307
346
308
347
Lagain:
309
348
310
349
const mask = tlsPass ? (MItlsctor | MItlsdtor) : (MIctor | MIdtor);
311
- auto ctors = tlsPass ? result ._tlsctors : result ._ctors;
350
+ auto ctors = tlsPass ? mgroup ._tlsctors : mgroup ._ctors;
312
351
size_t cidx;
313
352
314
- ModuleInfo * [] mods = modules ;
353
+ ModuleInfo * [] mods = mgroup._modules ;
315
354
size_t idx;
316
355
while (true )
317
356
{
@@ -375,7 +414,7 @@ private SortedCtors sortCtorsImpl(ModuleInfo*[] modules, StackRec[] stack)
375
414
/* Internal runtime error, dependency on an uninitialized
376
415
* module outside of the current module group.
377
416
*/
378
- (stackidx < modules .length) || assert (0 );
417
+ (stackidx < mgroup._modules .length) || assert (0 );
379
418
380
419
// recurse
381
420
stack[stackidx++ ] = StackRec(mods, idx);
@@ -400,22 +439,18 @@ private SortedCtors sortCtorsImpl(ModuleInfo*[] modules, StackRec[] stack)
400
439
break ;
401
440
}
402
441
// store final number
403
- tlsPass ? result ._tlsctors : result ._ctors = ctors[0 .. cidx];
442
+ tlsPass ? mgroup ._tlsctors : mgroup ._ctors = ctors[0 .. cidx];
404
443
405
444
// clean flags
406
- for (size_t i = 0 ; i < modules.length; ++ i)
407
- { auto m = modules[i];
445
+ foreach (m; mgroup._modules)
408
446
m.flags = m.flags & ~ (MIctorstart | MIctordone);
409
- }
410
447
411
448
// rerun for TLS constructors
412
449
if (! tlsPass)
413
450
{
414
451
tlsPass = true ;
415
452
goto Lagain;
416
453
}
417
-
418
- return result;
419
454
}
420
455
421
456
version (unittest )
@@ -470,12 +505,12 @@ unittest
470
505
471
506
void checkExp (ModuleInfo * [] dtors=null , ModuleInfo * [] tlsdtors=null )
472
507
{
473
- auto ptrs = [&m0, &m1, &m2];
474
- auto sorted = sortCtors(ptrs );
475
- foreach (m; ptrs )
508
+ auto mgroup = ModuleGroup( [&m0, &m1, &m2]) ;
509
+ mgroup. sortCtors();
510
+ foreach (m; mgroup._modules )
476
511
assert (! (m.flags & (MIctorstart | MIctordone)));
477
- assert (sorted ._ctors == dtors);
478
- assert (sorted ._tlsctors == tlsdtors);
512
+ assert (mgroup ._ctors == dtors);
513
+ assert (mgroup ._tlsctors == tlsdtors);
479
514
}
480
515
481
516
// no ctors
0 commit comments