comparison tango/lib/compiler/llvmdc/genobj.d @ 132:1700239cab2e trunk

[svn r136] MAJOR UNSTABLE UPDATE!!! Initial commit after moving to Tango instead of Phobos. Lots of bugfixes... This build is not suitable for most things.
author lindquist
date Fri, 11 Jan 2008 17:57:40 +0100
parents
children 44a95ac7368a
comparison
equal deleted inserted replaced
131:5825d48b27d1 132:1700239cab2e
1 /**
2 * Part of the D programming language runtime library.
3 * Forms the symbols available to all D programs. Includes
4 * Object, which is the root of the class object hierarchy.
5 *
6 * This module is implicitly imported.
7 * Macros:
8 * WIKI = Object
9 */
10
11 /*
12 * Copyright (C) 2004-2007 by Digital Mars, www.digitalmars.com
13 * Written by Walter Bright
14 *
15 * This software is provided 'as-is', without any express or implied
16 * warranty. In no event will the authors be held liable for any damages
17 * arising from the use of this software.
18 *
19 * Permission is granted to anyone to use this software for any purpose,
20 * including commercial applications, and to alter it and redistribute it
21 * freely, in both source and binary form, subject to the following
22 * restrictions:
23 *
24 * o The origin of this software must not be misrepresented; you must not
25 * claim that you wrote the original software. If you use this software
26 * in a product, an acknowledgment in the product documentation would be
27 * appreciated but is not required.
28 * o Altered source versions must be plainly marked as such, and must not
29 * be misrepresented as being the original software.
30 * o This notice may not be removed or altered from any source
31 * distribution.
32 */
33
34 /*
35 * Modified by Sean Kelly <sean@f4.ca> for use with Tango.
36 */
37
38 module object;
39
40 private
41 {
42 import tango.stdc.string; // : memcmp, memcpy;
43 import tango.stdc.stdlib; // : calloc, realloc, free;
44 import util.string;
45 debug(PRINTF) import tango.stdc.stdio; // : printf;
46
47 extern (C) void onOutOfMemoryError();
48 extern (C) Object _d_newclass(ClassInfo ci);
49 }
50
51 // NOTE: For some reason, this declaration method doesn't work
52 // in this particular file (and this file only). It must
53 // be a DMD thing.
54 //alias typeof(int.sizeof) size_t;
55 //alias typeof(cast(void*)0 - cast(void*)0) ptrdiff_t;
56
57 version( X86_64 )
58 {
59 alias ulong size_t;
60 alias long ptrdiff_t;
61 }
62 else
63 {
64 alias uint size_t;
65 alias int ptrdiff_t;
66 }
67
68 alias size_t hash_t;
69
70 /**
71 * All D class objects inherit from Object.
72 */
73 class Object
74 {
75 /**
76 * Convert Object to a human readable string.
77 */
78 char[] toString()
79 {
80 return this.classinfo.name;
81 }
82
83 /**
84 * Compute hash function for Object.
85 */
86 hash_t toHash()
87 {
88 // BUG: this prevents a compacting GC from working, needs to be fixed
89 return cast(hash_t)cast(void*)this;
90 }
91
92 /**
93 * Compare with another Object obj.
94 * Returns:
95 * $(TABLE
96 * $(TR $(TD this &lt; obj) $(TD &lt; 0))
97 * $(TR $(TD this == obj) $(TD 0))
98 * $(TR $(TD this &gt; obj) $(TD &gt; 0))
99 * )
100 */
101 int opCmp(Object o)
102 {
103 // BUG: this prevents a compacting GC from working, needs to be fixed
104 //return cast(int)cast(void*)this - cast(int)cast(void*)o;
105
106 //throw new Exception("need opCmp for class " ~ this.classinfo.name);
107 return this !is o;
108 }
109
110 /**
111 * Returns !=0 if this object does have the same contents as obj.
112 */
113 int opEquals(Object o)
114 {
115 return cast(int)(this is o);
116 }
117
118 interface Monitor
119 {
120 void lock();
121 void unlock();
122 }
123 }
124
125 /**
126 * Information about an interface.
127 * A pointer to this appears as the first entry in the interface's vtbl[].
128 */
129 struct Interface
130 {
131 ClassInfo classinfo; /// .classinfo for this interface (not for containing class)
132 void*[] vtbl;
133 ptrdiff_t offset; /// offset to Interface 'this' from Object 'this'
134 }
135
136 /**
137 * Runtime type information about a class. Can be retrieved for any class type
138 * or instance by using the .classinfo property.
139 * A pointer to this appears as the first entry in the class's vtbl[].
140 */
141 class ClassInfo : Object
142 {
143 byte[] init; /** class static initializer
144 * (init.length gives size in bytes of class)
145 */
146 char[] name; /// class name
147 void*[] vtbl; /// virtual function pointer table
148 Interface[] interfaces; /// interfaces this class implements
149 ClassInfo base; /// base class
150 void* destructor;
151 void function(Object) classInvariant;
152 uint flags;
153 // 1: // IUnknown
154 // 2: // has no possible pointers into GC memory
155 // 4: // has offTi[] member
156 // 8: // has constructors
157 void* deallocator;
158 OffsetTypeInfo[] offTi;
159 void function(Object) defaultConstructor; // default Constructor
160
161 /**
162 * Search all modules for ClassInfo corresponding to classname.
163 * Returns: null if not found
164 */
165 static ClassInfo find(char[] classname)
166 {
167 foreach (m; ModuleInfo)
168 {
169 //writefln("module %s, %d", m.name, m.localClasses.length);
170 foreach (c; m.localClasses)
171 {
172 //writefln("\tclass %s", c.name);
173 if (c.name == classname)
174 return c;
175 }
176 }
177 return null;
178 }
179
180 /**
181 * Create instance of Object represented by 'this'.
182 */
183 Object create()
184 {
185 if (flags & 8 && !defaultConstructor)
186 return null;
187 Object o = _d_newclass(this);
188 if (flags & 8 && defaultConstructor)
189 {
190 defaultConstructor(o);
191 }
192 return o;
193 }
194 }
195
196 /**
197 * Array of pairs giving the offset and type information for each
198 * member in an aggregate.
199 */
200 struct OffsetTypeInfo
201 {
202 size_t offset; /// Offset of member from start of object
203 TypeInfo ti; /// TypeInfo for this member
204 }
205
206 /**
207 * Runtime type information about a type.
208 * Can be retrieved for any type using a
209 * <a href="../expression.html#typeidexpression">TypeidExpression</a>.
210 */
211 class TypeInfo
212 {
213 hash_t toHash()
214 { hash_t hash;
215
216 foreach (char c; this.toString())
217 hash = hash * 9 + c;
218 return hash;
219 }
220
221 int opCmp(Object o)
222 {
223 if (this is o)
224 return 0;
225 TypeInfo ti = cast(TypeInfo)o;
226 if (ti is null)
227 return 1;
228 return stringCompare(this.toString(), ti.toString());
229 }
230
231 int opEquals(Object o)
232 {
233 /* TypeInfo instances are singletons, but duplicates can exist
234 * across DLL's. Therefore, comparing for a name match is
235 * sufficient.
236 */
237 if (this is o)
238 return 1;
239 TypeInfo ti = cast(TypeInfo)o;
240 return cast(int)(ti && this.toString() == ti.toString());
241 }
242
243 /// Returns a hash of the instance of a type.
244 hash_t getHash(void *p) { return cast(hash_t)p; }
245
246 /// Compares two instances for equality.
247 int equals(void *p1, void *p2) { return cast(int)(p1 == p2); }
248
249 /// Compares two instances for &lt;, ==, or &gt;.
250 int compare(void *p1, void *p2) { return 0; }
251
252 /// Returns size of the type.
253 size_t tsize() { return 0; }
254
255 /// Swaps two instances of the type.
256 void swap(void *p1, void *p2)
257 {
258 size_t n = tsize();
259 for (size_t i = 0; i < n; i++)
260 { byte t;
261
262 t = (cast(byte *)p1)[i];
263 (cast(byte *)p1)[i] = (cast(byte *)p2)[i];
264 (cast(byte *)p2)[i] = t;
265 }
266 }
267
268 /// Get TypeInfo for 'next' type, as defined by what kind of type this is,
269 /// null if none.
270 TypeInfo next() { return null; }
271
272 /// Return default initializer, null if default initialize to 0
273 void[] init() { return null; }
274
275 /// Get flags for type: 1 means GC should scan for pointers
276 uint flags() { return 0; }
277
278 /// Get type information on the contents of the type; null if not available
279 OffsetTypeInfo[] offTi() { return null; }
280 }
281
282 class TypeInfo_Typedef : TypeInfo
283 {
284 char[] toString() { return name; }
285
286 int opEquals(Object o)
287 { TypeInfo_Typedef c;
288
289 return cast(int)
290 (this is o ||
291 ((c = cast(TypeInfo_Typedef)o) !is null &&
292 this.name == c.name &&
293 this.base == c.base));
294 }
295
296 hash_t getHash(void *p) { return base.getHash(p); }
297 int equals(void *p1, void *p2) { return base.equals(p1, p2); }
298 int compare(void *p1, void *p2) { return base.compare(p1, p2); }
299 size_t tsize() { return base.tsize(); }
300 void swap(void *p1, void *p2) { return base.swap(p1, p2); }
301
302 TypeInfo next() { return base.next(); }
303 uint flags() { return base.flags(); }
304 void[] init() { return m_init.length ? m_init : base.init(); }
305
306 TypeInfo base;
307 char[] name;
308 void[] m_init;
309 }
310
311 class TypeInfo_Enum : TypeInfo_Typedef
312 {
313 }
314
315 class TypeInfo_Pointer : TypeInfo
316 {
317 char[] toString() { return m_next.toString() ~ "*"; }
318
319 int opEquals(Object o)
320 { TypeInfo_Pointer c;
321
322 return this is o ||
323 ((c = cast(TypeInfo_Pointer)o) !is null &&
324 this.m_next == c.m_next);
325 }
326
327 hash_t getHash(void *p)
328 {
329 return cast(hash_t)*cast(void**)p;
330 }
331
332 int equals(void *p1, void *p2)
333 {
334 return cast(int)(*cast(void* *)p1 == *cast(void* *)p2);
335 }
336
337 int compare(void *p1, void *p2)
338 {
339 if (*cast(void* *)p1 < *cast(void* *)p2)
340 return -1;
341 else if (*cast(void* *)p1 > *cast(void* *)p2)
342 return 1;
343 else
344 return 0;
345 }
346
347 size_t tsize()
348 {
349 return (void*).sizeof;
350 }
351
352 void swap(void *p1, void *p2)
353 { void* tmp;
354 tmp = *cast(void**)p1;
355 *cast(void**)p1 = *cast(void**)p2;
356 *cast(void**)p2 = tmp;
357 }
358
359 TypeInfo next() { return m_next; }
360 uint flags() { return 1; }
361
362 TypeInfo m_next;
363 }
364
365 class TypeInfo_Array : TypeInfo
366 {
367 char[] toString() { return value.toString() ~ "[]"; }
368
369 int opEquals(Object o)
370 { TypeInfo_Array c;
371
372 return cast(int)
373 (this is o ||
374 ((c = cast(TypeInfo_Array)o) !is null &&
375 this.value == c.value));
376 }
377
378 hash_t getHash(void *p)
379 { size_t sz = value.tsize();
380 hash_t hash = 0;
381 void[] a = *cast(void[]*)p;
382 for (size_t i = 0; i < a.length; i++)
383 hash += value.getHash(a.ptr + i * sz);
384 return hash;
385 }
386
387 int equals(void *p1, void *p2)
388 {
389 void[] a1 = *cast(void[]*)p1;
390 void[] a2 = *cast(void[]*)p2;
391 if (a1.length != a2.length)
392 return 0;
393 size_t sz = value.tsize();
394 for (size_t i = 0; i < a1.length; i++)
395 {
396 if (!value.equals(a1.ptr + i * sz, a2.ptr + i * sz))
397 return 0;
398 }
399 return 1;
400 }
401
402 int compare(void *p1, void *p2)
403 {
404 void[] a1 = *cast(void[]*)p1;
405 void[] a2 = *cast(void[]*)p2;
406 size_t sz = value.tsize();
407 size_t len = a1.length;
408
409 if (a2.length < len)
410 len = a2.length;
411 for (size_t u = 0; u < len; u++)
412 {
413 int result = value.compare(a1.ptr + u * sz, a2.ptr + u * sz);
414 if (result)
415 return result;
416 }
417 return cast(int)a1.length - cast(int)a2.length;
418 }
419
420 size_t tsize()
421 {
422 return (void[]).sizeof;
423 }
424
425 void swap(void *p1, void *p2)
426 { void[] tmp;
427 tmp = *cast(void[]*)p1;
428 *cast(void[]*)p1 = *cast(void[]*)p2;
429 *cast(void[]*)p2 = tmp;
430 }
431
432 TypeInfo value;
433
434 TypeInfo next()
435 {
436 return value;
437 }
438
439 uint flags() { return 1; }
440 }
441
442 class TypeInfo_StaticArray : TypeInfo
443 {
444 char[] toString()
445 {
446 char [10] tmp = void;
447 return value.toString() ~ "[" ~ intToUtf8(tmp, len) ~ "]";
448 }
449
450 int opEquals(Object o)
451 { TypeInfo_StaticArray c;
452
453 return cast(int)
454 (this is o ||
455 ((c = cast(TypeInfo_StaticArray)o) !is null &&
456 this.len == c.len &&
457 this.value == c.value));
458 }
459
460 hash_t getHash(void *p)
461 { size_t sz = value.tsize();
462 hash_t hash = 0;
463 for (size_t i = 0; i < len; i++)
464 hash += value.getHash(p + i * sz);
465 return hash;
466 }
467
468 int equals(void *p1, void *p2)
469 {
470 size_t sz = value.tsize();
471
472 for (size_t u = 0; u < len; u++)
473 {
474 if (!value.equals(p1 + u * sz, p2 + u * sz))
475 return 0;
476 }
477 return 1;
478 }
479
480 int compare(void *p1, void *p2)
481 {
482 size_t sz = value.tsize();
483
484 for (size_t u = 0; u < len; u++)
485 {
486 int result = value.compare(p1 + u * sz, p2 + u * sz);
487 if (result)
488 return result;
489 }
490 return 0;
491 }
492
493 size_t tsize()
494 {
495 return len * value.tsize();
496 }
497
498 void swap(void *p1, void *p2)
499 { void* tmp;
500 size_t sz = value.tsize();
501 ubyte[16] buffer;
502 void* pbuffer;
503
504 if (sz < buffer.sizeof)
505 tmp = buffer.ptr;
506 else
507 tmp = pbuffer = (new void[sz]).ptr;
508
509 for (size_t u = 0; u < len; u += sz)
510 { size_t o = u * sz;
511 memcpy(tmp, p1 + o, sz);
512 memcpy(p1 + o, p2 + o, sz);
513 memcpy(p2 + o, tmp, sz);
514 }
515 if (pbuffer)
516 delete pbuffer;
517 }
518
519 void[] init() { return value.init(); }
520 TypeInfo next() { return value; }
521 uint flags() { return value.flags(); }
522
523 TypeInfo value;
524 size_t len;
525 }
526
527 class TypeInfo_AssociativeArray : TypeInfo
528 {
529 char[] toString()
530 {
531 return next.toString() ~ "[" ~ key.toString() ~ "]";
532 }
533
534 int opEquals(Object o)
535 { TypeInfo_AssociativeArray c;
536
537 return this is o ||
538 ((c = cast(TypeInfo_AssociativeArray)o) !is null &&
539 this.key == c.key &&
540 this.value == c.value);
541 }
542
543 // BUG: need to add the rest of the functions
544
545 size_t tsize()
546 {
547 return (char[int]).sizeof;
548 }
549
550 TypeInfo next() { return value; }
551 uint flags() { return 1; }
552
553 TypeInfo value;
554 TypeInfo key;
555 }
556
557 class TypeInfo_Function : TypeInfo
558 {
559 char[] toString()
560 {
561 return next.toString() ~ "()";
562 }
563
564 int opEquals(Object o)
565 { TypeInfo_Function c;
566
567 return this is o ||
568 ((c = cast(TypeInfo_Function)o) !is null &&
569 this.next == c.next);
570 }
571
572 // BUG: need to add the rest of the functions
573
574 size_t tsize()
575 {
576 return 0; // no size for functions
577 }
578
579 TypeInfo next;
580 }
581
582 class TypeInfo_Delegate : TypeInfo
583 {
584 char[] toString()
585 {
586 return next.toString() ~ " delegate()";
587 }
588
589 int opEquals(Object o)
590 { TypeInfo_Delegate c;
591
592 return this is o ||
593 ((c = cast(TypeInfo_Delegate)o) !is null &&
594 this.next == c.next);
595 }
596
597 // BUG: need to add the rest of the functions
598
599 size_t tsize()
600 { alias int delegate() dg;
601 return dg.sizeof;
602 }
603
604 uint flags() { return 1; }
605
606 TypeInfo next;
607 }
608
609 class TypeInfo_Class : TypeInfo
610 {
611 char[] toString() { return info.name; }
612
613 int opEquals(Object o)
614 { TypeInfo_Class c;
615
616 return this is o ||
617 ((c = cast(TypeInfo_Class)o) !is null &&
618 this.info.name == c.classinfo.name);
619 }
620
621 hash_t getHash(void *p)
622 {
623 Object o = *cast(Object*)p;
624 assert(o);
625 return o.toHash();
626 }
627
628 int equals(void *p1, void *p2)
629 {
630 Object o1 = *cast(Object*)p1;
631 Object o2 = *cast(Object*)p2;
632
633 return (o1 is o2) || (o1 && o1.opEquals(o2));
634 }
635
636 int compare(void *p1, void *p2)
637 {
638 Object o1 = *cast(Object*)p1;
639 Object o2 = *cast(Object*)p2;
640 int c = 0;
641
642 // Regard null references as always being "less than"
643 if (o1 !is o2)
644 {
645 if (o1)
646 { if (!o2)
647 c = 1;
648 else
649 c = o1.opCmp(o2);
650 }
651 else
652 c = -1;
653 }
654 return c;
655 }
656
657 size_t tsize()
658 {
659 return Object.sizeof;
660 }
661
662 uint flags() { return 1; }
663
664 OffsetTypeInfo[] offTi()
665 {
666 return (info.flags & 4) ? info.offTi : null;
667 }
668
669 ClassInfo info;
670 }
671
672 class TypeInfo_Interface : TypeInfo
673 {
674 char[] toString() { return info.name; }
675
676 int opEquals(Object o)
677 { TypeInfo_Interface c;
678
679 return this is o ||
680 ((c = cast(TypeInfo_Interface)o) !is null &&
681 this.info.name == c.classinfo.name);
682 }
683
684 hash_t getHash(void *p)
685 {
686 Interface* pi = **cast(Interface ***)*cast(void**)p;
687 Object o = cast(Object)(*cast(void**)p - pi.offset);
688 assert(o);
689 return o.toHash();
690 }
691
692 int equals(void *p1, void *p2)
693 {
694 Interface* pi = **cast(Interface ***)*cast(void**)p1;
695 Object o1 = cast(Object)(*cast(void**)p1 - pi.offset);
696 pi = **cast(Interface ***)*cast(void**)p2;
697 Object o2 = cast(Object)(*cast(void**)p2 - pi.offset);
698
699 return o1 == o2 || (o1 && o1.opCmp(o2) == 0);
700 }
701
702 int compare(void *p1, void *p2)
703 {
704 Interface* pi = **cast(Interface ***)*cast(void**)p1;
705 Object o1 = cast(Object)(*cast(void**)p1 - pi.offset);
706 pi = **cast(Interface ***)*cast(void**)p2;
707 Object o2 = cast(Object)(*cast(void**)p2 - pi.offset);
708 int c = 0;
709
710 // Regard null references as always being "less than"
711 if (o1 != o2)
712 {
713 if (o1)
714 { if (!o2)
715 c = 1;
716 else
717 c = o1.opCmp(o2);
718 }
719 else
720 c = -1;
721 }
722 return c;
723 }
724
725 size_t tsize()
726 {
727 return Object.sizeof;
728 }
729
730 uint flags() { return 1; }
731
732 ClassInfo info;
733 }
734
735 class TypeInfo_Struct : TypeInfo
736 {
737 char[] toString() { return name; }
738
739 int opEquals(Object o)
740 { TypeInfo_Struct s;
741
742 return this is o ||
743 ((s = cast(TypeInfo_Struct)o) !is null &&
744 this.name == s.name &&
745 this.init.length == s.init.length);
746 }
747
748 hash_t getHash(void *p)
749 { hash_t h;
750
751 assert(p);
752 if (xtoHash)
753 { debug(PRINTF) printf("getHash() using xtoHash\n");
754 h = (*xtoHash)(p);
755 }
756 else
757 {
758 debug(PRINTF) printf("getHash() using default hash\n");
759 // A sorry hash algorithm.
760 // Should use the one for strings.
761 // BUG: relies on the GC not moving objects
762 for (size_t i = 0; i < init.length; i++)
763 { h = h * 9 + *cast(ubyte*)p;
764 p++;
765 }
766 }
767 return h;
768 }
769
770 int equals(void *p2, void *p1)
771 { int c;
772
773 if (p1 == p2)
774 c = 1;
775 else if (!p1 || !p2)
776 c = 0;
777 else if (xopEquals)
778 c = (*xopEquals)(p1, p2);
779 else
780 // BUG: relies on the GC not moving objects
781 c = (memcmp(p1, p2, init.length) == 0);
782 return c;
783 }
784
785 int compare(void *p2, void *p1)
786 {
787 int c = 0;
788
789 // Regard null references as always being "less than"
790 if (p1 != p2)
791 {
792 if (p1)
793 { if (!p2)
794 c = 1;
795 else if (xopCmp)
796 c = (*xopCmp)(p1, p2);
797 else
798 // BUG: relies on the GC not moving objects
799 c = memcmp(p1, p2, init.length);
800 }
801 else
802 c = -1;
803 }
804 return c;
805 }
806
807 size_t tsize()
808 {
809 return init.length;
810 }
811
812 void[] init() { return m_init; }
813
814 uint flags() { return m_flags; }
815
816 char[] name;
817 void[] m_init; // initializer; init.ptr == null if 0 initialize
818
819 hash_t function(void*) xtoHash;
820 int function(void*,void*) xopEquals;
821 int function(void*,void*) xopCmp;
822 char[] function(void*) xtoString;
823
824 uint m_flags;
825 }
826
827 class TypeInfo_Tuple : TypeInfo
828 {
829 TypeInfo[] elements;
830
831 char[] toString()
832 {
833 char[] s;
834 s = "(";
835 foreach (i, element; elements)
836 {
837 if (i)
838 s ~= ',';
839 s ~= element.toString();
840 }
841 s ~= ")";
842 return s;
843 }
844
845 int opEquals(Object o)
846 {
847 if (this is o)
848 return 1;
849
850 auto t = cast(TypeInfo_Tuple)o;
851 if (t && elements.length == t.elements.length)
852 {
853 for (size_t i = 0; i < elements.length; i++)
854 {
855 if (elements[i] != t.elements[i])
856 return 0;
857 }
858 return 1;
859 }
860 return 0;
861 }
862
863 hash_t getHash(void *p)
864 {
865 assert(0);
866 }
867
868 int equals(void *p1, void *p2)
869 {
870 assert(0);
871 }
872
873 int compare(void *p1, void *p2)
874 {
875 assert(0);
876 }
877
878 size_t tsize()
879 {
880 assert(0);
881 }
882
883 void swap(void *p1, void *p2)
884 {
885 assert(0);
886 }
887 }
888
889 class Exception : Object
890 {
891 char[] msg;
892 char[] file;
893 size_t line;
894 Exception next;
895
896 this(char[] msg, Exception next = null)
897 {
898 this.msg = msg;
899 this.next = next;
900 }
901
902 this(char[] msg, char[] file, size_t line, Exception next = null)
903 {
904 this(msg, next);
905 this.file = file;
906 this.line = line;
907 }
908
909 char[] toString()
910 {
911 return msg;
912 }
913 }
914
915
916 ////////////////////////////////////////////////////////////////////////////////
917 // ModuleInfo
918 ////////////////////////////////////////////////////////////////////////////////
919
920
921 enum
922 {
923 MIctorstart = 1, // we've started constructing it
924 MIctordone = 2, // finished construction
925 MIstandalone = 4, // module ctor does not depend on other module
926 // ctors being done first
927 MIhasictor = 8, // has ictor member
928 }
929
930
931 class ModuleInfo
932 {
933 char[] name;
934 ModuleInfo[] importedModules;
935 ClassInfo[] localClasses;
936 uint flags;
937
938 void function() ctor; // module static constructor (order dependent)
939 void function() dtor; // module static destructor
940 void function() unitTest; // module unit tests
941
942 void* xgetMembers; // module getMembers() function
943
944 void function() ictor; // module static constructor (order independent)
945
946 static int opApply( int delegate( inout ModuleInfo ) dg )
947 {
948 int ret = 0;
949
950 foreach( m; _moduleinfo_array )
951 {
952 ret = dg( m );
953 if( ret )
954 break;
955 }
956 return ret;
957 }
958 }
959
960
961 // Win32: this gets initialized by minit.asm
962 // linux: this gets initialized in _moduleCtor()
963 extern (C) ModuleInfo[] _moduleinfo_array;
964
965
966 version (linux)
967 {
968 // This linked list is created by a compiler generated function inserted
969 // into the .ctor list by the compiler.
970 struct ModuleReference
971 {
972 ModuleReference* next;
973 ModuleInfo mod;
974 }
975
976 extern (C) ModuleReference* _Dmodule_ref; // start of linked list
977 }
978
979 ModuleInfo[] _moduleinfo_dtors;
980 uint _moduleinfo_dtors_i;
981
982 // Register termination function pointers
983 extern (C) int _fatexit(void *);
984
985 /**
986 * Initialize the modules.
987 */
988
989 extern (C) void _moduleCtor()
990 {
991 debug(PRINTF) printf("_moduleCtor()\n");
992 version (linux)
993 {
994 int len = 0;
995 ModuleReference *mr;
996
997 for (mr = _Dmodule_ref; mr; mr = mr.next)
998 len++;
999 _moduleinfo_array = new ModuleInfo[len];
1000 len = 0;
1001 for (mr = _Dmodule_ref; mr; mr = mr.next)
1002 { _moduleinfo_array[len] = mr.mod;
1003 len++;
1004 }
1005 }
1006
1007 version (Win32)
1008 {
1009 // Ensure module destructors also get called on program termination
1010 //_fatexit(&_STD_moduleDtor);
1011 }
1012
1013 _moduleinfo_dtors = new ModuleInfo[_moduleinfo_array.length];
1014 debug(PRINTF) printf("_moduleinfo_dtors = x%x\n", cast(void *)_moduleinfo_dtors);
1015 _moduleIndependentCtors();
1016 _moduleCtor2(_moduleinfo_array, 0);
1017 }
1018
1019 extern (C) void _moduleIndependentCtors()
1020 {
1021 debug(PRINTF) printf("_moduleIndependentCtors()\n");
1022 foreach (m; _moduleinfo_array)
1023 {
1024 if (m && m.flags & MIhasictor && m.ictor)
1025 {
1026 (*m.ictor)();
1027 }
1028 }
1029 }
1030
1031 void _moduleCtor2(ModuleInfo[] mi, int skip)
1032 {
1033 debug(PRINTF) printf("_moduleCtor2(): %d modules\n", mi.length);
1034 for (uint i = 0; i < mi.length; i++)
1035 {
1036 ModuleInfo m = mi[i];
1037
1038 debug(PRINTF) printf("\tmodule[%d] = '%p'\n", i, m);
1039 if (!m)
1040 continue;
1041 debug(PRINTF) printf("\tmodule[%d] = '%.*s'\n", i, m.name);
1042 if (m.flags & MIctordone)
1043 continue;
1044 debug(PRINTF) printf("\tmodule[%d] = '%.*s', m = x%x\n", i, m.name, m);
1045
1046 if (m.ctor || m.dtor)
1047 {
1048 if (m.flags & MIctorstart)
1049 { if (skip || m.flags & MIstandalone)
1050 continue;
1051 throw new Exception( "Cyclic dependency in module " ~ m.name );
1052 }
1053
1054 m.flags |= MIctorstart;
1055 _moduleCtor2(m.importedModules, 0);
1056 if (m.ctor)
1057 (*m.ctor)();
1058 m.flags &= ~MIctorstart;
1059 m.flags |= MIctordone;
1060
1061 // Now that construction is done, register the destructor
1062 //printf("\tadding module dtor x%x\n", m);
1063 assert(_moduleinfo_dtors_i < _moduleinfo_dtors.length);
1064 _moduleinfo_dtors[_moduleinfo_dtors_i++] = m;
1065 }
1066 else
1067 {
1068 m.flags |= MIctordone;
1069 _moduleCtor2(m.importedModules, 1);
1070 }
1071 }
1072 }
1073
1074 /**
1075 * Destruct the modules.
1076 */
1077
1078 // Starting the name with "_STD" means under linux a pointer to the
1079 // function gets put in the .dtors segment.
1080
1081 extern (C) void _moduleDtor()
1082 {
1083 debug(PRINTF) printf("_moduleDtor(): %d modules\n", _moduleinfo_dtors_i);
1084
1085 for (uint i = _moduleinfo_dtors_i; i-- != 0;)
1086 {
1087 ModuleInfo m = _moduleinfo_dtors[i];
1088
1089 debug(PRINTF) printf("\tmodule[%d] = '%.*s', x%x\n", i, m.name, m);
1090 if (m.dtor)
1091 {
1092 (*m.dtor)();
1093 }
1094 }
1095 debug(PRINTF) printf("_moduleDtor() done\n");
1096 }
1097
1098 ////////////////////////////////////////////////////////////////////////////////
1099 // Monitor
1100 ////////////////////////////////////////////////////////////////////////////////
1101
1102 alias Object.Monitor IMonitor;
1103
1104 struct Monitor
1105 {
1106 IMonitor impl;
1107 /* stuff */
1108 }
1109
1110 Monitor* getMonitor(Object h)
1111 {
1112 return cast(Monitor*) (cast(void**) h)[1];
1113 }
1114
1115 void setMonitor(Object h, Monitor* m)
1116 {
1117 (cast(void**) h)[1] = m;
1118 }
1119
1120 extern (C) void _d_monitor_create(Object);
1121 extern (C) void _d_monitor_destroy(Object);
1122 extern (C) void _d_monitor_lock(Object);
1123 extern (C) int _d_monitor_unlock(Object);
1124
1125 extern (C) void _d_monitordelete(Object h, bool det)
1126 {
1127 Monitor* m = getMonitor(h);
1128
1129 if (m !is null)
1130 {
1131 IMonitor i = m.impl;
1132 if (i is null)
1133 {
1134 _d_monitor_destroy(h);
1135 setMonitor(h, null);
1136 return;
1137 }
1138 if (det && (cast(void*) i) !is (cast(void*) h))
1139 delete i;
1140 setMonitor(h, null);
1141 }
1142 }
1143
1144 extern (C) void _d_monitorenter(Object h)
1145 {
1146 Monitor* m = getMonitor(h);
1147
1148 if (m is null)
1149 {
1150 _d_monitor_create(h);
1151 m = getMonitor(h);
1152 }
1153
1154 IMonitor i = m.impl;
1155
1156 if (i is null)
1157 {
1158 _d_monitor_lock(h);
1159 return;
1160 }
1161 i.lock();
1162 }
1163
1164 extern (C) void _d_monitorexit(Object h)
1165 {
1166 Monitor* m = getMonitor(h);
1167 IMonitor i = m.impl;
1168
1169 if (i is null)
1170 {
1171 _d_monitor_unlock(h);
1172 return;
1173 }
1174 i.unlock();
1175 }