Note: This website is archived. For up-to-date information about D projects and development, please visit wiki.dlang.org.

root/trunk/src/object_.d

Revision 376, 58.3 kB (checked in by sean, 14 years ago)

Reverted changes to stdc.math. The routines aren't pure.

  • Property svn:eol-style set to native
Line 
1 /**
2  * Forms the symbols available to all D programs. Includes Object, which is
3  * the root of the class object hierarchy.  This module is implicitly
4  * imported.
5  * Macros:
6  *      WIKI = Object
7  *
8  * Copyright: Copyright Digital Mars 2000 - 2010.
9  * License:   <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
10  * Authors:   Walter Bright, Sean Kelly
11  */
12
13 /*          Copyright Digital Mars 2000 - 2009.
14  * Distributed under the Boost Software License, Version 1.0.
15  *    (See accompanying file LICENSE_1_0.txt or copy at
16  *          http://www.boost.org/LICENSE_1_0.txt)
17  */
18
19 module object;
20
21 //debug=PRINTF;
22
23 private
24 {
25     import core.atomic;
26     import core.stdc.string;
27     import core.stdc.stdlib;
28     import rt.util.hash;
29     import rt.util.string;
30     debug(PRINTF) import core.stdc.stdio;
31
32     extern (C) void onOutOfMemoryError();
33     extern (C) Object _d_newclass(TypeInfo_Class ci);
34     extern (C) void _d_arrayshrinkfit(TypeInfo ti, void[] arr);
35     extern (C) size_t _d_arraysetcapacity(TypeInfo ti, size_t newcapacity, void *arrptr);
36 }
37
38 // NOTE: For some reason, this declaration method doesn't work
39 //       in this particular file (and this file only).  It must
40 //       be a DMD thing.
41 //alias typeof(int.sizeof)                    size_t;
42 //alias typeof(cast(void*)0 - cast(void*)0)   ptrdiff_t;
43
44 version(X86_64)
45 {
46     alias ulong size_t;
47     alias long  ptrdiff_t;
48     alias long  sizediff_t;
49 }
50 else
51 {
52     alias uint  size_t;
53     alias int   ptrdiff_t;
54     alias int   sizediff_t;
55 }
56
57 alias size_t hash_t;
58 alias bool equals_t;
59
60 alias immutable(char)[]  string;
61 alias immutable(wchar)[] wstring;
62 alias immutable(dchar)[] dstring;
63
64 /**
65  * All D class objects inherit from Object.
66  */
67 class Object
68 {
69     /**
70      * Convert Object to a human readable string.
71      */
72     string toString()
73     {
74         return this.classinfo.name;
75     }
76
77     /**
78      * Compute hash function for Object.
79      */
80     hash_t toHash()
81     {
82         // BUG: this prevents a compacting GC from working, needs to be fixed
83         return cast(hash_t)cast(void*)this;
84     }
85
86     /**
87      * Compare with another Object obj.
88      * Returns:
89      *  $(TABLE
90      *  $(TR $(TD this &lt; obj) $(TD &lt; 0))
91      *  $(TR $(TD this == obj) $(TD 0))
92      *  $(TR $(TD this &gt; obj) $(TD &gt; 0))
93      *  )
94      */
95     int opCmp(Object o)
96     {
97         // BUG: this prevents a compacting GC from working, needs to be fixed
98         //return cast(int)cast(void*)this - cast(int)cast(void*)o;
99
100         throw new Exception("need opCmp for class " ~ this.classinfo.name);
101         //return this !is o;
102     }
103
104     /**
105      * Returns !=0 if this object does have the same contents as obj.
106      */
107     equals_t opEquals(Object o)
108     {
109         return this is o;
110     }
111    
112     equals_t opEquals(Object lhs, Object rhs)
113     {
114         if (lhs is rhs)
115             return true;
116         if (lhs is null || rhs is null)
117             return false;
118         if (typeid(lhs) == typeid(rhs))
119             return lhs.opEquals(rhs);
120         return lhs.opEquals(rhs) &&
121                rhs.opEquals(lhs);
122     }
123
124     interface Monitor
125     {
126         void lock();
127         void unlock();
128     }
129
130     /**
131      * Create instance of class specified by classname.
132      * The class must either have no constructors or have
133      * a default constructor.
134      * Returns:
135      *   null if failed
136      */
137     static Object factory(string classname)
138     {
139         auto ci = TypeInfo_Class.find(classname);
140         if (ci)
141         {
142             return ci.create();
143         }
144         return null;
145     }
146 }
147
148 /************************
149  * Returns true if lhs and rhs are equal.
150  */
151 bool opEquals(Object lhs, Object rhs)
152 {
153     // If aliased to the same object or both null => equal
154     if (lhs is rhs) return true;
155
156     // If either is null => non-equal
157     if (lhs is null || rhs is null) return false;
158
159     // If same exact type => one call to method opEquals
160     if (typeid(lhs) is typeid(rhs) || typeid(lhs).opEquals(typeid(rhs)))
161         return lhs.opEquals(rhs);
162
163     // General case => symmetric calls to method opEquals
164     return lhs.opEquals(rhs) && rhs.opEquals(lhs);
165 }
166
167 bool opEquals(TypeInfo lhs, TypeInfo rhs)
168 {
169     // If aliased to the same object or both null => equal
170     if (lhs is rhs) return true;
171
172     // If either is null => non-equal
173     if (lhs is null || rhs is null) return false;
174
175     // If same exact type => one call to method opEquals
176     if (typeid(lhs) == typeid(rhs)) return lhs.opEquals(rhs);
177
178     //printf("%.*s and %.*s, %d %d\n", lhs.toString(), rhs.toString(), lhs.opEquals(rhs), rhs.opEquals(lhs));
179
180     // Factor out top level const
181     // (This still isn't right, should follow same rules as compiler does for type equality.)
182     TypeInfo_Const c = cast(TypeInfo_Const) lhs;
183     if (c)
184     lhs = c.base;
185     c = cast(TypeInfo_Const) rhs;
186     if (c)
187     rhs = c.base;
188
189     // General case => symmetric calls to method opEquals
190     return lhs.opEquals(rhs) && rhs.opEquals(lhs);
191 }
192
193 /**
194  * Information about an interface.
195  * When an object is accessed via an interface, an Interface* appears as the
196  * first entry in its vtbl.
197  */
198 struct Interface
199 {
200     TypeInfo_Class   classinfo;  /// .classinfo for this interface (not for containing class)
201     void*[]     vtbl;
202     ptrdiff_t   offset;     /// offset to Interface 'this' from Object 'this'
203 }
204
205 /**
206  * Runtime type information about a class. Can be retrieved for any class type
207  * or instance by using the .classinfo property.
208  * A pointer to this appears as the first entry in the class's vtbl[].
209  */
210 alias TypeInfo_Class Classinfo;
211
212 /**
213  * Array of pairs giving the offset and type information for each
214  * member in an aggregate.
215  */
216 struct OffsetTypeInfo
217 {
218     size_t   offset;    /// Offset of member from start of object
219     TypeInfo ti;        /// TypeInfo for this member
220 }
221
222 /**
223  * Runtime type information about a type.
224  * Can be retrieved for any type using a
225  * <a href="../expression.html#typeidexpression">TypeidExpression</a>.
226  */
227 class TypeInfo
228 {
229     override hash_t toHash()
230     {
231         auto data = this.toString();
232         return hashOf(data.ptr, data.length);
233     }
234
235     override int opCmp(Object o)
236     {
237         if (this is o)
238             return 0;
239         TypeInfo ti = cast(TypeInfo)o;
240         if (ti is null)
241             return 1;
242         return dstrcmp(this.toString(), ti.toString());
243     }
244
245     override equals_t opEquals(Object o)
246     {
247         /* TypeInfo instances are singletons, but duplicates can exist
248          * across DLL's. Therefore, comparing for a name match is
249          * sufficient.
250          */
251         if (this is o)
252             return true;
253         TypeInfo ti = cast(TypeInfo)o;
254         return ti && this.toString() == ti.toString();
255     }
256
257     /// Returns a hash of the instance of a type.
258     hash_t getHash(in void* p) { return cast(hash_t)p; }
259
260     /// Compares two instances for equality.
261     equals_t equals(in void* p1, in void* p2) { return p1 == p2; }
262
263     /// Compares two instances for &lt;, ==, or &gt;.
264     int compare(in void* p1, in void* p2) { return 0; }
265
266     /// Returns size of the type.
267     size_t tsize() { return 0; }
268
269     /// Swaps two instances of the type.
270     void swap(void* p1, void* p2)
271     {
272         size_t n = tsize();
273         for (size_t i = 0; i < n; i++)
274         {
275             byte t = (cast(byte *)p1)[i];
276             (cast(byte*)p1)[i] = (cast(byte*)p2)[i];
277             (cast(byte*)p2)[i] = t;
278         }
279     }
280
281     /// Get TypeInfo for 'next' type, as defined by what kind of type this is,
282     /// null if none.
283     TypeInfo next() { return null; }
284
285     /// Return default initializer, null if default initialize to 0
286     void[] init() { return null; }
287
288     /// Get flags for type: 1 means GC should scan for pointers
289     uint flags() { return 0; }
290
291     /// Get type information on the contents of the type; null if not available
292     OffsetTypeInfo[] offTi() { return null; }
293     /// Run the destructor on the object and all its sub-objects
294     void destroy(void* p) {}
295     /// Run the postblit on the object and all its sub-objects
296     void postblit(void* p) {}
297 }
298
299 class TypeInfo_Typedef : TypeInfo
300 {
301     override string toString() { return name; }
302
303     override equals_t opEquals(Object o)
304     {
305         TypeInfo_Typedef c;
306         return this is o ||
307                ((c = cast(TypeInfo_Typedef)o) !is null &&
308                 this.name == c.name &&
309                 this.base == c.base);
310     }
311
312     override hash_t getHash(in void* p) { return base.getHash(p); }
313     override equals_t equals(in void* p1, in void* p2) { return base.equals(p1, p2); }
314     override int compare(in void* p1, in void* p2) { return base.compare(p1, p2); }
315     override size_t tsize() { return base.tsize(); }
316     override void swap(void* p1, void* p2) { return base.swap(p1, p2); }
317
318     override TypeInfo next() { return base.next(); }
319     override uint flags() { return base.flags(); }
320     override void[] init() { return m_init.length ? m_init : base.init(); }
321
322     TypeInfo base;
323     string   name;
324     void[]   m_init;
325 }
326
327 class TypeInfo_Enum : TypeInfo_Typedef
328 {
329
330 }
331
332 class TypeInfo_Pointer : TypeInfo
333 {
334     override string toString() { return m_next.toString() ~ "*"; }
335
336     override equals_t opEquals(Object o)
337     {
338         TypeInfo_Pointer c;
339         return this is o ||
340                 ((c = cast(TypeInfo_Pointer)o) !is null &&
341                  this.m_next == c.m_next);
342     }
343
344     override hash_t getHash(in void* p)
345     {
346         return cast(hash_t)*cast(void**)p;
347     }
348
349     override equals_t equals(in void* p1, in void* p2)
350     {
351         return *cast(void**)p1 == *cast(void**)p2;
352     }
353
354     override int compare(in void* p1, in void* p2)
355     {
356         if (*cast(void**)p1 < *cast(void**)p2)
357             return -1;
358         else if (*cast(void**)p1 > *cast(void**)p2)
359             return 1;
360         else
361             return 0;
362     }
363
364     override size_t tsize()
365     {
366         return (void*).sizeof;
367     }
368
369     override void swap(void* p1, void* p2)
370     {
371         void* tmp = *cast(void**)p1;
372         *cast(void**)p1 = *cast(void**)p2;
373         *cast(void**)p2 = tmp;
374     }
375
376     override TypeInfo next() { return m_next; }
377     override uint flags() { return 1; }
378
379     TypeInfo m_next;
380 }
381
382 class TypeInfo_Array : TypeInfo
383 {
384     override string toString() { return value.toString() ~ "[]"; }
385
386     override equals_t opEquals(Object o)
387     {
388         TypeInfo_Array c;
389         return this is o ||
390                ((c = cast(TypeInfo_Array)o) !is null &&
391                 this.value == c.value);
392     }
393
394     override hash_t getHash(in void* p)
395     {
396         void[] a = *cast(void[]*)p;
397         return hashOf(a.ptr, a.length);
398     }
399
400     override equals_t equals(in void* p1, in void* p2)
401     {
402         void[] a1 = *cast(void[]*)p1;
403         void[] a2 = *cast(void[]*)p2;
404         if (a1.length != a2.length)
405             return false;
406         size_t sz = value.tsize();
407         for (size_t i = 0; i < a1.length; i++)
408         {
409             if (!value.equals(a1.ptr + i * sz, a2.ptr + i * sz))
410                 return false;
411         }
412         return true;
413     }
414
415     override int compare(in void* p1, in void* p2)
416     {
417         void[] a1 = *cast(void[]*)p1;
418         void[] a2 = *cast(void[]*)p2;
419         size_t sz = value.tsize();
420         size_t len = a1.length;
421
422         if (a2.length < len)
423             len = a2.length;
424         for (size_t u = 0; u < len; u++)
425         {
426             int result = value.compare(a1.ptr + u * sz, a2.ptr + u * sz);
427             if (result)
428                 return result;
429         }
430         return cast(int)a1.length - cast(int)a2.length;
431     }
432
433     override size_t tsize()
434     {
435         return (void[]).sizeof;
436     }
437
438     override void swap(void* p1, void* p2)
439     {
440         void[] tmp = *cast(void[]*)p1;
441         *cast(void[]*)p1 = *cast(void[]*)p2;
442         *cast(void[]*)p2 = tmp;
443     }
444
445     TypeInfo value;
446
447     override TypeInfo next()
448     {
449         return value;
450     }
451
452     override uint flags() { return 1; }
453 }
454
455 class TypeInfo_StaticArray : TypeInfo
456 {
457     override string toString()
458     {
459         char[20] tmp = void;
460         return cast(string)(value.toString() ~ "[" ~ tmp.ulongToString(len) ~ "]");
461     }
462
463     override equals_t opEquals(Object o)
464     {
465         TypeInfo_StaticArray c;
466         return this is o ||
467                ((c = cast(TypeInfo_StaticArray)o) !is null &&
468                 this.len == c.len &&
469                 this.value == c.value);
470     }
471
472     override hash_t getHash(in void* p)
473     {
474         size_t sz = value.tsize();
475         hash_t hash = 0;
476         for (size_t i = 0; i < len; i++)
477             hash += value.getHash(p + i * sz);
478         return hash;
479     }
480
481     override equals_t equals(in void* p1, in void* p2)
482     {
483         size_t sz = value.tsize();
484
485         for (size_t u = 0; u < len; u++)
486         {
487             if (!value.equals(p1 + u * sz, p2 + u * sz))
488                 return false;
489         }
490         return true;
491     }
492
493     override int compare(in void* p1, in void* p2)
494     {
495         size_t sz = value.tsize();
496
497         for (size_t u = 0; u < len; u++)
498         {
499             int result = value.compare(p1 + u * sz, p2 + u * sz);
500             if (result)
501                 return result;
502         }
503         return 0;
504     }
505
506     override size_t tsize()
507     {
508         return len * value.tsize();
509     }
510
511     override void swap(void* p1, void* p2)
512     {
513         void* tmp;
514         size_t sz = value.tsize();
515         ubyte[16] buffer;
516         void* pbuffer;
517
518         if (sz < buffer.sizeof)
519             tmp = buffer.ptr;
520         else
521             tmp = pbuffer = (new void[sz]).ptr;
522
523         for (size_t u = 0; u < len; u += sz)
524         {   size_t o = u * sz;
525             memcpy(tmp, p1 + o, sz);
526             memcpy(p1 + o, p2 + o, sz);
527             memcpy(p2 + o, tmp, sz);
528         }
529         if (pbuffer)
530             delete pbuffer;
531     }
532
533     override void[] init() { return value.init(); }
534     override TypeInfo next() { return value; }
535     override uint flags() { return value.flags(); }
536
537     override void destroy(void* p)
538     {
539         auto sz = value.tsize();
540         p += sz * len;
541         foreach (i; 0 .. len)
542         {
543             p -= sz;
544             value.destroy(p);
545         }
546     }
547
548     override void postblit(void* p)
549     {
550         auto sz = value.tsize();
551         foreach (i; 0 .. len)
552         {
553             value.postblit(p);
554             p += sz;
555         }
556     }
557
558     TypeInfo value;
559     size_t   len;
560 }
561
562 class TypeInfo_AssociativeArray : TypeInfo
563 {
564     override string toString()
565     {
566         return cast(string)(next.toString() ~ "[" ~ key.toString() ~ "]");
567     }
568
569     override equals_t opEquals(Object o)
570     {
571         TypeInfo_AssociativeArray c;
572         return this is o ||
573                 ((c = cast(TypeInfo_AssociativeArray)o) !is null &&
574                  this.key == c.key &&
575                  this.value == c.value);
576     }
577
578     // BUG: need to add the rest of the functions
579
580     override size_t tsize()
581     {
582         return (char[int]).sizeof;
583     }
584
585     override TypeInfo next() { return value; }
586     override uint flags() { return 1; }
587
588     TypeInfo value;
589     TypeInfo key;
590
591     TypeInfo impl;
592 }
593
594 class TypeInfo_Function : TypeInfo
595 {
596     override string toString()
597     {
598         return cast(string)(next.toString() ~ "()");
599     }
600
601     override equals_t opEquals(Object o)
602     {
603         TypeInfo_Function c;
604         return this is o ||
605                 ((c = cast(TypeInfo_Function)o) !is null &&
606                  this.next == c.next);
607     }
608
609     // BUG: need to add the rest of the functions
610
611     override size_t tsize()
612     {
613         return 0;       // no size for functions
614     }
615
616     TypeInfo next;
617 }
618
619 class TypeInfo_Delegate : TypeInfo
620 {
621     override string toString()
622     {
623         return cast(string)(next.toString() ~ " delegate()");
624     }
625
626     override equals_t opEquals(Object o)
627     {
628         TypeInfo_Delegate c;
629         return this is o ||
630                 ((c = cast(TypeInfo_Delegate)o) !is null &&
631                  this.next == c.next);
632     }
633
634     // BUG: need to add the rest of the functions
635
636     override size_t tsize()
637     {
638         alias int delegate() dg;
639         return dg.sizeof;
640     }
641
642     override uint flags() { return 1; }
643
644     TypeInfo next;
645 }
646
647 class TypeInfo_Class : TypeInfo
648 {
649     override string toString() { return info.name; }
650
651     override equals_t opEquals(Object o)
652     {
653         TypeInfo_Class c;
654         return this is o ||
655                 ((c = cast(TypeInfo_Class)o) !is null &&
656                  this.info.name == c.classinfo.name);
657     }
658
659     override hash_t getHash(in void* p)
660     {
661         Object o = *cast(Object*)p;
662         return o ? o.toHash() : 0;
663     }
664
665     override equals_t equals(in void* p1, in void* p2)
666     {
667         Object o1 = *cast(Object*)p1;
668         Object o2 = *cast(Object*)p2;
669
670         return (o1 is o2) || (o1 && o1.opEquals(o2));
671     }
672
673     override int compare(in void* p1, in void* p2)
674     {
675         Object o1 = *cast(Object*)p1;
676         Object o2 = *cast(Object*)p2;
677         int c = 0;
678
679         // Regard null references as always being "less than"
680         if (o1 !is o2)
681         {
682             if (o1)
683             {
684                 if (!o2)
685                     c = 1;
686                 else
687                     c = o1.opCmp(o2);
688             }
689             else
690                 c = -1;
691         }
692         return c;
693     }
694
695     override size_t tsize()
696     {
697         return Object.sizeof;
698     }
699
700     override uint flags() { return 1; }
701
702     override OffsetTypeInfo[] offTi()
703     {
704         return m_offTi;
705     }
706
707     @property TypeInfo_Class info() { return this; }
708     @property TypeInfo typeinfo() { return this; }
709
710     byte[]      init;           /** class static initializer
711                                  * (init.length gives size in bytes of class)
712                                  */
713     string      name;           /// class name
714     void*[]     vtbl;           /// virtual function pointer table
715     Interface[] interfaces;     /// interfaces this class implements
716     TypeInfo_Class   base;           /// base class
717     void*       destructor;
718     void function(Object) classInvariant;
719     uint        m_flags;
720     //  1:                      // is IUnknown or is derived from IUnknown
721     //  2:                      // has no possible pointers into GC memory
722     //  4:                      // has offTi[] member
723     //  8:                      // has constructors
724     // 16:                      // has xgetMembers member
725     // 32:                      // has typeinfo member
726     void*       deallocator;
727     OffsetTypeInfo[] m_offTi;
728     void function(Object) defaultConstructor;   // default Constructor
729     const(MemberInfo[]) function(in char[]) xgetMembers;
730
731     /**
732      * Search all modules for TypeInfo_Class corresponding to classname.
733      * Returns: null if not found
734      */
735     static TypeInfo_Class find(in char[] classname)
736     {
737         foreach (m; ModuleInfo)
738         {
739       if (m)
740             //writefln("module %s, %d", m.name, m.localClasses.length);
741             foreach (c; m.localClasses)
742             {
743                 //writefln("\tclass %s", c.name);
744                 if (c.name == classname)
745                     return c;
746             }
747         }
748         return null;
749     }
750
751     /**
752      * Create instance of Object represented by 'this'.
753      */
754     Object create()
755     {
756         if (m_flags & 8 && !defaultConstructor)
757             return null;
758         Object o = _d_newclass(this);
759         if (m_flags & 8 && defaultConstructor)
760         {
761             defaultConstructor(o);
762         }
763         return o;
764     }
765
766     /**
767      * Search for all members with the name 'name'.
768      * If name[] is null, return all members.
769      */
770     const(MemberInfo[]) getMembers(in char[] name)
771     {
772         if (m_flags & 16 && xgetMembers)
773             return xgetMembers(name);
774         return null;
775     }
776 }
777
778 alias TypeInfo_Class ClassInfo;
779
780 class TypeInfo_Interface : TypeInfo
781 {
782     override string toString() { return info.name; }
783
784     override equals_t opEquals(Object o)
785     {
786         TypeInfo_Interface c;
787         return this is o ||
788                 ((c = cast(TypeInfo_Interface)o) !is null &&
789                  this.info.name == c.classinfo.name);
790     }
791
792     override hash_t getHash(in void* p)
793     {
794         Interface* pi = **cast(Interface ***)*cast(void**)p;
795         Object o = cast(Object)(*cast(void**)p - pi.offset);
796         assert(o);
797         return o.toHash();
798     }
799
800     override equals_t equals(in void* p1, in void* p2)
801     {
802         Interface* pi = **cast(Interface ***)*cast(void**)p1;
803         Object o1 = cast(Object)(*cast(void**)p1 - pi.offset);
804         pi = **cast(Interface ***)*cast(void**)p2;
805         Object o2 = cast(Object)(*cast(void**)p2 - pi.offset);
806
807         return o1 == o2 || (o1 && o1.opCmp(o2) == 0);
808     }
809
810     override int compare(in void* p1, in void* p2)
811     {
812         Interface* pi = **cast(Interface ***)*cast(void**)p1;
813         Object o1 = cast(Object)(*cast(void**)p1 - pi.offset);
814         pi = **cast(Interface ***)*cast(void**)p2;
815         Object o2 = cast(Object)(*cast(void**)p2 - pi.offset);
816         int c = 0;
817
818         // Regard null references as always being "less than"
819         if (o1 != o2)
820         {
821             if (o1)
822             {
823                 if (!o2)
824                     c = 1;
825                 else
826                     c = o1.opCmp(o2);
827             }
828             else
829                 c = -1;
830         }
831         return c;
832     }
833
834     override size_t tsize()
835     {
836         return Object.sizeof;
837     }
838
839     override uint flags() { return 1; }
840
841     TypeInfo_Class info;
842 }
843
844 class TypeInfo_Struct : TypeInfo
845 {
846     override string toString() { return name; }
847
848     override equals_t opEquals(Object o)
849     {
850         TypeInfo_Struct s;
851         return this is o ||
852                 ((s = cast(TypeInfo_Struct)o) !is null &&
853                  this.name == s.name &&
854                  this.init.length == s.init.length);
855     }
856
857     override hash_t getHash(in void* p)
858     {
859         assert(p);
860         if (xtoHash)
861         {
862             debug(PRINTF) printf("getHash() using xtoHash\n");
863             return (*xtoHash)(p);
864         }
865         else
866         {
867             debug(PRINTF) printf("getHash() using default hash\n");
868             return hashOf(p, init.length);
869         }
870     }
871
872     override equals_t equals(in void* p1, in void* p2)
873     {
874         if (p1 == p2)
875             return true;
876         else if (!p1 || !p2)
877             return false;
878         else if (xopEquals)
879             return (*xopEquals)(p1, p2);
880         else
881             // BUG: relies on the GC not moving objects
882             return memcmp(p1, p2, init.length) == 0;
883     }
884
885     override int compare(in void* p1, in void* p2)
886     {
887         // Regard null references as always being "less than"
888         if (p1 != p2)
889         {
890             if (p1)
891             {
892                 if (!p2)
893                     return true;
894                 else if (xopCmp)
895                     return (*xopCmp)(p2, p1);
896                 else
897                     // BUG: relies on the GC not moving objects
898                     return memcmp(p1, p2, init.length);
899             }
900             else
901                 return -1;
902         }
903         return 0;
904     }
905
906     override size_t tsize()
907     {
908         return init.length;
909     }
910
911     override void[] init() { return m_init; }
912
913     override uint flags() { return m_flags; }
914
915     override void destroy(void* p)
916     {
917         if (xdtor)
918             (*xdtor)(p);
919     }
920
921     override void postblit(void* p)
922     {
923         if (xpostblit)
924             (*xpostblit)(p);
925     }
926
927     string name;
928     void[] m_init;      // initializer; init.ptr == null if 0 initialize
929
930     hash_t   function(in void*)           xtoHash;
931     equals_t function(in void*, in void*) xopEquals;
932     int      function(in void*, in void*) xopCmp;
933     char[]   function(in void*)           xtoString;
934
935     uint m_flags;
936
937     const(MemberInfo[]) function(in char[]) xgetMembers;
938     void function(void*)                    xdtor;
939     void function(void*)                    xpostblit;
940 }
941
942 class TypeInfo_Tuple : TypeInfo
943 {
944     TypeInfo[] elements;
945
946     override string toString()
947     {
948         string s = "(";
949         foreach (i, element; elements)
950         {
951             if (i)
952                 s ~= ',';
953             s ~= element.toString();
954         }
955         s ~= ")";
956         return s;
957     }
958
959     override equals_t opEquals(Object o)
960     {
961         if (this is o)
962             return true;
963
964         auto t = cast(TypeInfo_Tuple)o;
965         if (t && elements.length == t.elements.length)
966         {
967             for (size_t i = 0; i < elements.length; i++)
968             {
969                 if (elements[i] != t.elements[i])
970                     return false;
971             }
972             return true;
973         }
974         return false;
975     }
976
977     override hash_t getHash(in void* p)
978     {
979         assert(0);
980     }
981
982     override equals_t equals(in void* p1, in void* p2)
983     {
984         assert(0);
985     }
986
987     override int compare(in void* p1, in void* p2)
988     {
989         assert(0);
990     }
991
992     override size_t tsize()
993     {
994         assert(0);
995     }
996
997     override void swap(void* p1, void* p2)
998     {
999         assert(0);
1000     }
1001
1002     override void destroy(void* p)
1003     {
1004         assert(0);
1005     }
1006
1007     override void postblit(void* p)
1008     {
1009         assert(0);
1010     }
1011 }
1012
1013 class TypeInfo_Const : TypeInfo
1014 {
1015     override string toString()
1016     {
1017         return cast(string) ("const(" ~ base.toString() ~ ")");
1018     }
1019
1020     //override equals_t opEquals(Object o) { return base.opEquals(o); }
1021     override equals_t opEquals(Object o)
1022     {
1023         if (this is o)
1024             return true;
1025
1026     if (typeid(this) != typeid(o))
1027         return false;
1028
1029         auto t = cast(TypeInfo_Const)o;
1030         if (base.opEquals(t.base))
1031         {
1032             return true;
1033         }
1034         return false;
1035     }
1036
1037     override hash_t getHash(in void *p) { return base.getHash(p); }
1038     override equals_t equals(in void *p1, in void *p2) { return base.equals(p1, p2); }
1039     override int compare(in void *p1, in void *p2) { return base.compare(p1, p2); }
1040     override size_t tsize() { return base.tsize(); }
1041     override void swap(void *p1, void *p2) { return base.swap(p1, p2); }
1042
1043     override TypeInfo next() { return base.next(); }
1044     override uint flags() { return base.flags(); }
1045     override void[] init() { return base.init(); }
1046
1047     TypeInfo base;
1048 }
1049
1050 class TypeInfo_Invariant : TypeInfo_Const
1051 {
1052     override string toString()
1053     {
1054         return cast(string) ("immutable(" ~ base.toString() ~ ")");
1055     }
1056 }
1057
1058 class TypeInfo_Shared : TypeInfo_Const
1059 {
1060     override string toString()
1061     {
1062         return cast(string) ("shared(" ~ base.toString() ~ ")");
1063     }
1064 }
1065
1066 class TypeInfo_Inout : TypeInfo_Const
1067 {
1068     override string toString()
1069     {
1070         return cast(string) ("inout(" ~ base.toString() ~ ")");
1071     }
1072 }
1073
1074 abstract class MemberInfo
1075 {
1076     string name();
1077 }
1078
1079 class MemberInfo_field : MemberInfo
1080 {
1081     this(string name, TypeInfo ti, size_t offset)
1082     {
1083         m_name = name;
1084         m_typeinfo = ti;
1085         m_offset = offset;
1086     }
1087
1088     override string name() { return m_name; }
1089     TypeInfo typeInfo() { return m_typeinfo; }
1090     size_t offset() { return m_offset; }
1091
1092     string   m_name;
1093     TypeInfo m_typeinfo;
1094     size_t   m_offset;
1095 }
1096
1097 class MemberInfo_function : MemberInfo
1098 {
1099     this(string name, TypeInfo ti, void* fp, uint flags)
1100     {
1101         m_name = name;
1102         m_typeinfo = ti;
1103         m_fp = fp;
1104         m_flags = flags;
1105     }
1106
1107     override string name() { return m_name; }
1108     TypeInfo typeInfo() { return m_typeinfo; }
1109     void* fp() { return m_fp; }
1110     uint flags() { return m_flags; }
1111
1112     string   m_name;
1113     TypeInfo m_typeinfo;
1114     void*    m_fp;
1115     uint     m_flags;
1116 }
1117
1118
1119 ///////////////////////////////////////////////////////////////////////////////
1120 // Throwable
1121 ///////////////////////////////////////////////////////////////////////////////
1122
1123
1124 class Throwable : Object
1125 {
1126     interface TraceInfo
1127     {
1128         int opApply(scope int delegate(ref char[]));
1129     }
1130
1131     string      msg;
1132     string      file;
1133     size_t      line;
1134     TraceInfo   info;
1135     Throwable   next;
1136
1137     this(string msg, Throwable next = null)
1138     {
1139         this.msg = msg;
1140         this.next = next;
1141         this.info = traceContext();
1142     }
1143
1144     this(string msg, string file, size_t line, Throwable next = null)
1145     {
1146         this(msg, next);
1147         this.file = file;
1148         this.line = line;
1149         this.info = traceContext();
1150     }
1151
1152     override string toString()
1153     {
1154         char[20] tmp = void;
1155         char[]   buf;
1156
1157         for (Throwable e = this; e !is null; e = e.next)
1158         {
1159             if (e.file)
1160             {
1161                buf ~= e.classinfo.name ~ "@" ~ e.file ~ "(" ~ tmp.ulongToString(e.line) ~ "): " ~ e.msg;
1162             }
1163             else
1164             {
1165                buf ~= e.classinfo.name ~ ": " ~ e.msg;
1166             }
1167             if (e.info)
1168             {
1169                 buf ~= "\n----------------";
1170                 foreach (t; e.info)
1171                     buf ~= "\n" ~ t;
1172             }
1173             if (e.next)
1174                 buf ~= "\n";
1175         }
1176         return cast(string) buf;
1177     }
1178 }
1179
1180
1181 alias Throwable.TraceInfo function(void* ptr = null) TraceHandler;
1182 private __gshared TraceHandler traceHandler = null;
1183
1184
1185 /**
1186  * Overrides the default trace hander with a user-supplied version.
1187  *
1188  * Params:
1189  *  h = The new trace handler.  Set to null to use the default handler.
1190  */
1191 extern (C) void  rt_setTraceHandler(TraceHandler h)
1192 {
1193     traceHandler = h;
1194 }
1195
1196 /**
1197  * Return the current trace handler
1198  */
1199 extern (C) TraceHandler rt_getTraceHandler()
1200 {
1201     return traceHandler;
1202 }
1203
1204 /**
1205  * This function will be called when an exception is constructed.  The
1206  * user-supplied trace handler will be called if one has been supplied,
1207  * otherwise no trace will be generated.
1208  *
1209  * Params:
1210  *  ptr = A pointer to the location from which to generate the trace, or null
1211  *        if the trace should be generated from within the trace handler
1212  *        itself.
1213  *
1214  * Returns:
1215  *  An object describing the current calling context or null if no handler is
1216  *  supplied.
1217  */
1218 Throwable.TraceInfo traceContext(void* ptr = null)
1219 {
1220     if (traceHandler is null)
1221         return null;
1222     return traceHandler(ptr);
1223 }
1224
1225
1226 class Exception : Throwable
1227 {
1228     this(string msg, Throwable next = null)
1229     {
1230         super(msg, next);
1231     }
1232
1233     this(string msg, string file, size_t line, Throwable next = null)
1234     {
1235         super(msg, file, line, next);
1236     }
1237 }
1238
1239
1240 class Error : Throwable
1241 {
1242     this(string msg, Throwable next = null)
1243     {
1244         super(msg, next);
1245     }
1246
1247     this(string msg, string file, size_t line, Throwable next = null)
1248     {
1249         super(msg, file, line, next);
1250     }
1251 }
1252
1253
1254 ///////////////////////////////////////////////////////////////////////////////
1255 // ModuleInfo
1256 ///////////////////////////////////////////////////////////////////////////////
1257
1258
1259 enum
1260 {
1261     MIctorstart  = 1,   // we've started constructing it
1262     MIctordone   = 2,   // finished construction
1263     MIstandalone = 4,   // module ctor does not depend on other module
1264                         // ctors being done first
1265     MItlsctor    = 8,
1266     MItlsdtor    = 0x10,
1267     MIctor       = 0x20,
1268     MIdtor       = 0x40,
1269     MIxgetMembers = 0x80,
1270     MIictor      = 0x100,
1271     MIunitTest   = 0x200,
1272     MIimportedModules = 0x400,
1273     MIlocalClasses = 0x800,
1274     MInew        = 0x80000000   // it's the "new" layout
1275 }
1276
1277
1278 struct ModuleInfo
1279 {
1280     struct New
1281     {
1282     uint flags;
1283     uint index;         // index into _moduleinfo_array[]
1284
1285     /* Order of appearance, depending on flags
1286      * tlsctor
1287      * tlsdtor
1288      * xgetMembers
1289      * ctor
1290      * dtor
1291      * ictor
1292      * importedModules
1293      * localClasses
1294      * name
1295      */
1296     }
1297     struct Old
1298     {
1299     string          name;
1300     ModuleInfo*[]    importedModules;
1301     TypeInfo_Class[]     localClasses;
1302     uint            flags;
1303
1304     void function() ctor;       // module shared static constructor (order dependent)
1305     void function() dtor;       // module shared static destructor
1306     void function() unitTest;   // module unit tests
1307
1308     void* xgetMembers;          // module getMembers() function
1309
1310     void function() ictor;      // module shared static constructor (order independent)
1311
1312     void function() tlsctor;    // module thread local static constructor (order dependent)
1313     void function() tlsdtor;    // module thread local static destructor
1314
1315     uint index;         // index into _moduleinfo_array[]
1316
1317     void*[1] reserved;          // for future expansion
1318     }
1319
1320     union
1321     {
1322     New n;
1323     Old o;
1324     }
1325
1326     @property isNew() { return n.flags & MInew; }
1327
1328     @property uint index() { return isNew ? n.index : o.index; }
1329     @property void index(uint i) { if (isNew) n.index = i; else o.index = i; }
1330
1331     @property uint flags() { return isNew ? n.flags : o.flags; }
1332     @property void flags(uint f) { if (isNew) n.flags = f; else o.flags = f; }
1333
1334     @property void function() tlsctor()
1335     {
1336     if (isNew)
1337     {
1338         if (n.flags & MItlsctor)
1339         {
1340         size_t off = New.sizeof;
1341         return *cast(typeof(return)*)(cast(void*)(&this) + off);
1342         }
1343         return null;
1344     }
1345     else
1346         return o.tlsctor;
1347     }
1348
1349     @property void function() tlsdtor()
1350     {
1351     if (isNew)
1352     {
1353         if (n.flags & MItlsdtor)
1354         {
1355         size_t off = New.sizeof;
1356         if (n.flags & MItlsctor)
1357             off += o.tlsctor.sizeof;
1358         return *cast(typeof(return)*)(cast(void*)(&this) + off);
1359         }
1360         return null;
1361     }
1362     else
1363         return o.tlsdtor;
1364     }
1365
1366     @property void* xgetMembers()
1367     {
1368     if (isNew)
1369     {
1370         if (n.flags & MIxgetMembers)
1371         {
1372         size_t off = New.sizeof;
1373         if (n.flags & MItlsctor)
1374             off += o.tlsctor.sizeof;
1375         if (n.flags & MItlsdtor)
1376             off += o.tlsdtor.sizeof;
1377         return *cast(typeof(return)*)(cast(void*)(&this) + off);
1378         }
1379         return null;
1380     }
1381     return o.xgetMembers;
1382     }
1383
1384     @property void function() ctor()
1385     {
1386     if (isNew)
1387     {
1388         if (n.flags & MIctor)
1389         {
1390         size_t off = New.sizeof;
1391         if (n.flags & MItlsctor)
1392             off += o.tlsctor.sizeof;
1393         if (n.flags & MItlsdtor)
1394             off += o.tlsdtor.sizeof;
1395         if (n.flags & MIxgetMembers)
1396             off += o.xgetMembers.sizeof;
1397         return *cast(typeof(return)*)(cast(void*)(&this) + off);
1398         }
1399         return null;
1400     }
1401     return o.ctor;
1402     }
1403
1404     @property void function() dtor()
1405     {
1406     if (isNew)
1407     {
1408         if (n.flags & MIdtor)
1409         {
1410         size_t off = New.sizeof;
1411         if (n.flags & MItlsctor)
1412             off += o.tlsctor.sizeof;
1413         if (n.flags & MItlsdtor)
1414             off += o.tlsdtor.sizeof;
1415         if (n.flags & MIxgetMembers)
1416             off += o.xgetMembers.sizeof;
1417         if (n.flags & MIctor)
1418             off += o.ctor.sizeof;
1419         return *cast(typeof(return)*)(cast(void*)(&this) + off);
1420         }
1421         return null;
1422     }
1423     return o.ctor;
1424     }
1425
1426     @property void function() ictor()
1427     {
1428     if (isNew)
1429     {
1430         if (n.flags & MIictor)
1431         {
1432         size_t off = New.sizeof;
1433         if (n.flags & MItlsctor)
1434             off += o.tlsctor.sizeof;
1435         if (n.flags & MItlsdtor)
1436             off += o.tlsdtor.sizeof;
1437         if (n.flags & MIxgetMembers)
1438             off += o.xgetMembers.sizeof;
1439         if (n.flags & MIctor)
1440             off += o.ctor.sizeof;
1441         if (n.flags & MIdtor)
1442             off += o.ctor.sizeof;
1443         return *cast(typeof(return)*)(cast(void*)(&this) + off);
1444         }
1445         return null;
1446     }
1447     return o.ictor;
1448     }
1449
1450     @property void function() unitTest()
1451     {
1452     if (isNew)
1453     {
1454         if (n.flags & MIunitTest)
1455         {
1456         size_t off = New.sizeof;
1457         if (n.flags & MItlsctor)
1458             off += o.tlsctor.sizeof;
1459         if (n.flags & MItlsdtor)
1460             off += o.tlsdtor.sizeof;
1461         if (n.flags & MIxgetMembers)
1462             off += o.xgetMembers.sizeof;
1463         if (n.flags & MIctor)
1464             off += o.ctor.sizeof;
1465         if (n.flags & MIdtor)
1466             off += o.ctor.sizeof;
1467         if (n.flags & MIictor)
1468             off += o.ictor.sizeof;
1469         return *cast(typeof(return)*)(cast(void*)(&this) + off);
1470         }
1471         return null;
1472     }
1473     return o.unitTest;
1474     }
1475
1476     @property ModuleInfo*[] importedModules()
1477     {
1478     if (isNew)
1479     {
1480         if (n.flags & MIimportedModules)
1481         {
1482         size_t off = New.sizeof;
1483         if (n.flags & MItlsctor)
1484             off += o.tlsctor.sizeof;
1485         if (n.flags & MItlsdtor)
1486             off += o.tlsdtor.sizeof;
1487         if (n.flags & MIxgetMembers)
1488             off += o.xgetMembers.sizeof;
1489         if (n.flags & MIctor)
1490             off += o.ctor.sizeof;
1491         if (n.flags & MIdtor)
1492             off += o.ctor.sizeof;
1493         if (n.flags & MIictor)
1494             off += o.ictor.sizeof;
1495         if (n.flags & MIunitTest)
1496             off += o.unitTest.sizeof;
1497         auto plength = cast(size_t*)(cast(void*)(&this) + off);
1498         ModuleInfo** pm = cast(ModuleInfo**)(plength + 1);
1499         return pm[0 .. *plength];
1500         }
1501         return null;
1502     }
1503     return o.importedModules;
1504     }
1505
1506     @property TypeInfo_Class[] localClasses()
1507     {
1508     if (isNew)
1509     {
1510         if (n.flags & MIlocalClasses)
1511         {
1512         size_t off = New.sizeof;
1513         if (n.flags & MItlsctor)
1514             off += o.tlsctor.sizeof;
1515         if (n.flags & MItlsdtor)
1516             off += o.tlsdtor.sizeof;
1517         if (n.flags & MIxgetMembers)
1518             off += o.xgetMembers.sizeof;
1519         if (n.flags & MIctor)
1520             off += o.ctor.sizeof;
1521         if (n.flags & MIdtor)
1522             off += o.ctor.sizeof;
1523         if (n.flags & MIictor)
1524             off += o.ictor.sizeof;
1525         if (n.flags & MIunitTest)
1526             off += o.unitTest.sizeof;
1527         if (n.flags & MIimportedModules)
1528         {
1529             auto plength = cast(size_t*)(cast(void*)(&this) + off);
1530             off += size_t.sizeof + *plength * plength.sizeof;
1531         }
1532         auto plength = cast(size_t*)(cast(void*)(&this) + off);
1533         TypeInfo_Class* pt = cast(TypeInfo_Class*)(plength + 1);
1534         return pt[0 .. *plength];
1535         }
1536         return null;
1537     }
1538     return o.localClasses;
1539     }
1540
1541     @property string name()
1542     {
1543     if (isNew)
1544     {
1545         size_t off = New.sizeof;
1546         if (n.flags & MItlsctor)
1547         off += o.tlsctor.sizeof;
1548         if (n.flags & MItlsdtor)
1549         off += o.tlsdtor.sizeof;
1550         if (n.flags & MIxgetMembers)
1551         off += o.xgetMembers.sizeof;
1552         if (n.flags & MIctor)
1553         off += o.ctor.sizeof;
1554         if (n.flags & MIdtor)
1555         off += o.ctor.sizeof;
1556         if (n.flags & MIictor)
1557         off += o.ictor.sizeof;
1558         if (n.flags & MIunitTest)
1559         off += o.unitTest.sizeof;
1560         if (n.flags & MIimportedModules)
1561         {
1562         auto plength = cast(size_t*)(cast(void*)(&this) + off);
1563         off += size_t.sizeof + *plength * plength.sizeof;
1564         }
1565         if (n.flags & MIlocalClasses)
1566         {
1567         auto plength = cast(size_t*)(cast(void*)(&this) + off);
1568         off += size_t.sizeof + *plength * plength.sizeof;
1569         }
1570         auto p = cast(immutable(char)*)(cast(void*)(&this) + off);
1571         auto len = strlen(p);
1572         return p[0 .. len];
1573     }
1574     return o.name;
1575     }
1576
1577
1578     static int opApply(scope int delegate(ref ModuleInfo*) dg)
1579     {
1580         int ret = 0;
1581
1582         foreach (m; _moduleinfo_array)
1583         {
1584             ret = dg(m);
1585             if (ret)
1586                 break;
1587         }
1588         return ret;
1589     }
1590 }
1591
1592
1593 // Windows: this gets initialized by minit.asm
1594 // Posix: this gets initialized in _moduleCtor()
1595 extern (C) __gshared ModuleInfo*[] _moduleinfo_array;
1596
1597
1598 version (linux)
1599 {
1600     // This linked list is created by a compiler generated function inserted
1601     // into the .ctor list by the compiler.
1602     struct ModuleReference
1603     {
1604         ModuleReference* next;
1605         ModuleInfo*      mod;
1606     }
1607
1608     extern (C) __gshared ModuleReference* _Dmodule_ref;   // start of linked list
1609 }
1610
1611 version (FreeBSD)
1612 {
1613     // This linked list is created by a compiler generated function inserted
1614     // into the .ctor list by the compiler.
1615     struct ModuleReference
1616     {
1617         ModuleReference* next;
1618         ModuleInfo*      mod;
1619     }
1620
1621     extern (C) __gshared ModuleReference* _Dmodule_ref;   // start of linked list
1622 }
1623
1624 version (Solaris)
1625 {
1626     // This linked list is created by a compiler generated function inserted
1627     // into the .ctor list by the compiler.
1628     struct ModuleReference
1629     {
1630         ModuleReference* next;
1631         ModuleInfo*      mod;
1632     }
1633
1634     extern (C) __gshared ModuleReference* _Dmodule_ref;   // start of linked list
1635 }
1636
1637 version (OSX)
1638 {
1639     extern (C)
1640     {
1641         extern __gshared void* _minfo_beg;
1642         extern __gshared void* _minfo_end;
1643     }
1644 }
1645
1646 __gshared ModuleInfo*[] _moduleinfo_dtors;
1647 __gshared uint          _moduleinfo_dtors_i;
1648
1649 ModuleInfo*[] _moduleinfo_tlsdtors;
1650 uint          _moduleinfo_tlsdtors_i;
1651
1652 // Register termination function pointers
1653 extern (C) int _fatexit(void*);
1654
1655 /**
1656  * Initialize the modules.
1657  */
1658
1659 extern (C) void _moduleCtor()
1660 {
1661     debug(PRINTF) printf("_moduleCtor()\n");
1662     version (linux)
1663     {
1664         int len = 0;
1665         ModuleReference *mr;
1666
1667         for (mr = _Dmodule_ref; mr; mr = mr.next)
1668             len++;
1669         _moduleinfo_array = new ModuleInfo*[len];
1670         len = 0;
1671         for (mr = _Dmodule_ref; mr; mr = mr.next)
1672         {   _moduleinfo_array[len] = mr.mod;
1673             len++;
1674         }
1675     }
1676
1677     version (FreeBSD)
1678     {
1679         int len = 0;
1680         ModuleReference *mr;
1681
1682         for (mr = _Dmodule_ref; mr; mr = mr.next)
1683             len++;
1684         _moduleinfo_array = new ModuleInfo*[len];
1685         len = 0;
1686         for (mr = _Dmodule_ref; mr; mr = mr.next)
1687         {   _moduleinfo_array[len] = mr.mod;
1688             len++;
1689         }
1690     }
1691
1692     version (Solaris)
1693     {
1694         int len = 0;
1695         ModuleReference *mr;
1696
1697         for (mr = _Dmodule_ref; mr; mr = mr.next)
1698             len++;
1699         _moduleinfo_array = new ModuleInfo*[len];
1700         len = 0;
1701         for (mr = _Dmodule_ref; mr; mr = mr.next)
1702         {   _moduleinfo_array[len] = mr.mod;
1703             len++;
1704         }
1705     }
1706
1707     version (OSX)
1708     {
1709         /* The ModuleInfo references are stored in the special segment
1710          * __minfodata, which is bracketed by the segments __minfo_beg
1711          * and __minfo_end. The variables _minfo_beg and _minfo_end
1712          * are of zero size and are in the two bracketing segments,
1713          * respectively.
1714          */
1715          size_t length = cast(ModuleInfo**)&_minfo_end - cast(ModuleInfo**)&_minfo_beg;
1716          _moduleinfo_array = (cast(ModuleInfo**)&_minfo_beg)[0 .. length];
1717          debug printf("moduleinfo: ptr = %p, length = %d\n", _moduleinfo_array.ptr, _moduleinfo_array.length);
1718
1719          debug foreach (m; _moduleinfo_array)
1720          {
1721              //printf("\t%p\n", m);
1722              printf("\t%.*s\n", m.name);
1723          }
1724     }   
1725
1726     version (Windows)
1727     {
1728         // Ensure module destructors also get called on program termination
1729         //_fatexit(&_STD_moduleDtor);
1730     }
1731
1732     _moduleinfo_dtors = new ModuleInfo*[_moduleinfo_array.length];
1733     debug(PRINTF) printf("_moduleinfo_dtors = x%x\n", cast(void*)_moduleinfo_dtors);
1734     _moduleIndependentCtors();
1735     _moduleCtor2(_moduleinfo_array, 0);
1736     // NOTE: _moduleTlsCtor is now called manually by dmain2
1737     //_moduleTlsCtor();
1738 }
1739
1740 extern (C) void _moduleIndependentCtors()
1741 {
1742     debug(PRINTF) printf("_moduleIndependentCtors()\n");
1743     foreach (m; _moduleinfo_array)
1744     {
1745         if (m && m.ictor)
1746         {
1747             (*m.ictor)();
1748         }
1749     }
1750 }
1751
1752 /********************************************
1753  * Run static constructors for shared global data.
1754  */
1755 void _moduleCtor2(ModuleInfo*[] mi, int skip)
1756 {
1757     debug(PRINTF) printf("_moduleCtor2(): %d modules\n", mi.length);
1758     for (uint i = 0; i < mi.length; i++)
1759     {
1760         ModuleInfo* m = mi[i];
1761
1762         debug(PRINTF) printf("\tmodule[%d] = %p\n", i, m);
1763         if (!m)
1764             continue;
1765         debug(PRINTF) printf("\tmodule[%d] = '%.*s'\n", i, m.name);
1766         if (m.flags & MIctordone)
1767             continue;
1768         debug(PRINTF) printf("\tmodule[%d] = '%.*s', m = x%x\n", i, m.name, m);
1769
1770         if (m.ctor || m.dtor)
1771         {
1772             if (m.flags & MIctorstart)
1773             {   if (skip || m.flags & MIstandalone)
1774                     continue;
1775         throw new Exception("Cyclic dependency in module " ~ m.name);
1776             }
1777
1778             m.flags = m.flags | MIctorstart;
1779             _moduleCtor2(m.importedModules, 0);
1780             if (m.ctor)
1781                 (*m.ctor)();
1782             m.flags = (m.flags & ~MIctorstart) | MIctordone;
1783
1784             // Now that construction is done, register the destructor
1785             //printf("\tadding module dtor x%x\n", m);
1786             assert(_moduleinfo_dtors_i < _moduleinfo_dtors.length);
1787             _moduleinfo_dtors[_moduleinfo_dtors_i++] = m;
1788         }
1789         else
1790         {
1791             m.flags = m.flags | MIctordone;
1792             _moduleCtor2(m.importedModules, 1);
1793         }
1794     }
1795 }
1796
1797 /********************************************
1798  * Run static constructors for thread local global data.
1799  */
1800
1801 extern (C) void _moduleTlsCtor()
1802 {
1803     debug(PRINTF) printf("_moduleTlsCtor()\n");
1804
1805     void* p = alloca(_moduleinfo_array.length * ubyte.sizeof);
1806     auto flags = cast(ubyte[])p[0 .. _moduleinfo_array.length];
1807     flags[] = 0;
1808
1809     foreach (uint i, m; _moduleinfo_array)
1810     {
1811     if (m)
1812         m.index = i;
1813     }
1814
1815     _moduleinfo_tlsdtors = new ModuleInfo*[_moduleinfo_array.length];
1816
1817     void _moduleTlsCtor2(ModuleInfo*[] mi, int skip)
1818     {
1819     debug(PRINTF) printf("_moduleTlsCtor2(skip = %d): %d modules\n", skip, mi.length);
1820     foreach (i, m; mi)
1821     {
1822         debug(PRINTF) printf("\tmodule[%d] = '%p'\n", i, m);
1823         if (!m)
1824         continue;
1825         debug(PRINTF) printf("\tmodule[%d] = '%.*s'\n", i, m.name);
1826         if (flags[m.index] & MIctordone)
1827         continue;
1828         debug(PRINTF) printf("\tmodule[%d] = '%.*s', m = x%x\n", i, m.name, m);
1829
1830         if (m.tlsctor || m.tlsdtor)
1831         {
1832         if (flags[m.index] & MIctorstart)
1833         {   if (skip || m.flags & MIstandalone)
1834             continue;
1835             throw new Exception("Cyclic dependency in module " ~ m.name);
1836         }
1837
1838         flags[m.index] |= MIctorstart;
1839         _moduleTlsCtor2(m.importedModules, 0);
1840         if (m.tlsctor)
1841             (*m.tlsctor)();
1842         flags[m.index] &= ~MIctorstart;
1843         flags[m.index] |= MIctordone;
1844
1845         // Now that construction is done, register the destructor
1846         //printf("**** adding module tlsdtor %p, [%d]\n", m, _moduleinfo_tlsdtors_i);
1847         assert(_moduleinfo_tlsdtors_i < _moduleinfo_tlsdtors.length);
1848         _moduleinfo_tlsdtors[_moduleinfo_tlsdtors_i++] = m;
1849         }
1850         else
1851         {
1852         flags[m.index] |= MIctordone;
1853         _moduleTlsCtor2(m.importedModules, 1);
1854         }
1855     }
1856     }
1857
1858     _moduleTlsCtor2(_moduleinfo_array, 0);
1859 }
1860
1861
1862 /**
1863  * Destruct the modules.
1864  */
1865
1866 // Starting the name with "_STD" means under Posix a pointer to the
1867 // function gets put in the .dtors segment.
1868
1869 extern (C) void _moduleDtor()
1870 {
1871     debug(PRINTF) printf("_moduleDtor(): %d modules\n", _moduleinfo_dtors_i);
1872
1873     // NOTE: _moduleTlsDtor is now called manually by dmain2
1874     //_moduleTlsDtor();
1875     for (uint i = _moduleinfo_dtors_i; i-- != 0;)
1876     {
1877         ModuleInfo* m = _moduleinfo_dtors[i];
1878
1879         debug(PRINTF) printf("\tmodule[%d] = '%.*s', x%x\n", i, m.name, m);
1880         if (m.dtor)
1881         {
1882             (*m.dtor)();
1883         }
1884     }
1885     debug(PRINTF) printf("_moduleDtor() done\n");
1886 }
1887
1888 extern (C) void _moduleTlsDtor()
1889 {
1890     debug(PRINTF) printf("_moduleTlsDtor(): %d modules\n", _moduleinfo_tlsdtors_i);
1891     version(none)
1892     {
1893         printf("_moduleinfo_tlsdtors = %d,%p\n", _moduleinfo_tlsdtors);
1894         foreach (i,m; _moduleinfo_tlsdtors[0..11])
1895             printf("[%d] = %p\n", i, m);
1896     }
1897
1898     for (uint i = _moduleinfo_tlsdtors_i; i-- != 0;)
1899     {
1900         ModuleInfo* m = _moduleinfo_tlsdtors[i];
1901
1902         debug(PRINTF) printf("\tmodule[%d] = '%.*s', x%x\n", i, m.name, m);
1903         if (m.tlsdtor)
1904         {
1905             (*m.tlsdtor)();
1906         }
1907     }
1908     debug(PRINTF) printf("_moduleTlsDtor() done\n");
1909 }
1910
1911 // Alias the TLS ctor and dtor using "rt_" prefixes, since these routines
1912 // must be called by core.thread.
1913
1914 extern (C) void rt_moduleTlsCtor()
1915 {
1916     _moduleTlsCtor();
1917 }
1918
1919 extern (C) void rt_moduleTlsDtor()
1920 {
1921     _moduleTlsDtor();
1922 }
1923
1924 ///////////////////////////////////////////////////////////////////////////////
1925 // Monitor
1926 ///////////////////////////////////////////////////////////////////////////////
1927
1928 alias Object.Monitor        IMonitor;
1929 alias void delegate(Object) DEvent;
1930
1931 // NOTE: The dtor callback feature is only supported for monitors that are not
1932 //       supplied by the user.  The assumption is that any object with a user-
1933 //       supplied monitor may have special storage or lifetime requirements and
1934 //       that as a result, storing references to local objects within Monitor
1935 //       may not be safe or desirable.  Thus, devt is only valid if impl is
1936 //       null.
1937 struct Monitor
1938 {
1939     IMonitor impl;
1940     /* internal */
1941     DEvent[] devt;
1942     size_t   refs;
1943     /* stuff */
1944 }
1945
1946 Monitor* getMonitor(Object h)
1947 {
1948     return cast(Monitor*) h.__monitor;
1949 }
1950
1951 void setMonitor(Object h, Monitor* m)
1952 {
1953     h.__monitor = m;
1954 }
1955
1956 void setSameMutex(shared Object ownee, shared Object owner)
1957 in
1958 {
1959     assert(ownee.__monitor is null);
1960 }
1961 body
1962 {
1963     auto m = cast(shared(Monitor)*) owner.__monitor;
1964
1965     if (m is null)
1966     {
1967         _d_monitor_create(cast(Object) owner);
1968         m = cast(shared(Monitor)*) owner.__monitor;
1969     }
1970    
1971     auto i = m.impl;
1972     if (i is null)
1973     {
1974         atomicOp!("+=")(m.refs, cast(size_t)1);
1975         ownee.__monitor = owner.__monitor;
1976         return;
1977     }
1978     // If m.impl is set (ie. if this is a user-created monitor), assume
1979     // the monitor is garbage collected and simply copy the reference.
1980     ownee.__monitor = owner.__monitor;
1981 }
1982
1983 extern (C) void _d_monitor_create(Object);
1984 extern (C) void _d_monitor_destroy(Object);
1985 extern (C) void _d_monitor_lock(Object);
1986 extern (C) int  _d_monitor_unlock(Object);
1987
1988 extern (C) void _d_monitordelete(Object h, bool det)
1989 {
1990     // det is true when the object is being destroyed deterministically (ie.
1991     // when it is explicitly deleted or is a scope object whose time is up).
1992     Monitor* m = getMonitor(h);
1993
1994     if (m !is null)
1995     {
1996         IMonitor i = m.impl;
1997         if (i is null)
1998         {
1999             auto s = cast(shared(Monitor)*) m;
2000             if(!atomicOp!("-=")(s.refs, cast(size_t) 1))
2001             {
2002                 _d_monitor_devt(m, h);
2003                 _d_monitor_destroy(h);
2004                 setMonitor(h, null);
2005             }
2006             return;
2007         }
2008         // NOTE: Since a monitor can be shared via setSameMutex it isn't safe
2009         //       to explicitly delete user-created monitors--there's no
2010         //       refcount and it may have multiple owners.
2011         /+
2012         if (det && (cast(void*) i) !is (cast(void*) h))
2013             delete i;
2014         +/
2015         setMonitor(h, null);
2016     }
2017 }
2018
2019 extern (C) void _d_monitorenter(Object h)
2020 {
2021     Monitor* m = getMonitor(h);
2022
2023     if (m is null)
2024     {
2025         _d_monitor_create(h);
2026         m = getMonitor(h);
2027     }
2028
2029     IMonitor i = m.impl;
2030
2031     if (i is null)
2032     {
2033         _d_monitor_lock(h);
2034         return;
2035     }
2036     i.lock();
2037 }
2038
2039 extern (C) void _d_monitorexit(Object h)
2040 {
2041     Monitor* m = getMonitor(h);
2042     IMonitor i = m.impl;
2043
2044     if (i is null)
2045     {
2046         _d_monitor_unlock(h);
2047         return;
2048     }
2049     i.unlock();
2050 }
2051
2052 extern (C) void _d_monitor_devt(Monitor* m, Object h)
2053 {
2054     if (m.devt.length)
2055     {
2056         DEvent[] devt;
2057
2058         synchronized (h)
2059         {
2060             devt = m.devt;
2061             m.devt = null;
2062         }
2063         foreach (v; devt)
2064         {
2065             if (v)
2066                 v(h);
2067         }
2068         free(devt.ptr);
2069     }
2070 }
2071
2072 extern (C) void rt_attachDisposeEvent(Object h, DEvent e)
2073 {
2074     synchronized (h)
2075     {
2076         Monitor* m = getMonitor(h);
2077         assert(m.impl is null);
2078
2079         foreach (ref v; m.devt)
2080         {
2081             if (v is null || v == e)
2082             {
2083                 v = e;
2084                 return;
2085             }
2086         }
2087
2088         auto len = m.devt.length + 4; // grow by 4 elements
2089         auto pos = m.devt.length;     // insert position
2090         auto p = realloc(m.devt.ptr, DEvent.sizeof * len);
2091         if (!p)
2092             onOutOfMemoryError();
2093         m.devt = (cast(DEvent*)p)[0 .. len];
2094         m.devt[pos+1 .. len] = null;
2095         m.devt[pos] = e;
2096     }
2097 }
2098
2099 extern (C) void rt_detachDisposeEvent(Object h, DEvent e)
2100 {
2101     synchronized (h)
2102     {
2103         Monitor* m = getMonitor(h);
2104         assert(m.impl is null);
2105
2106         foreach (p, v; m.devt)
2107         {
2108             if (v == e)
2109             {
2110                 memmove(&m.devt[p],
2111                         &m.devt[p+1],
2112                         (m.devt.length - p - 1) * DEvent.sizeof);
2113                 m.devt[$ - 1] = null;
2114                 return;
2115             }
2116         }
2117     }
2118 }
2119
2120 extern (C)
2121 {
2122     // from druntime/src/compiler/dmd/aaA.d
2123
2124     size_t _aaLen(void* p);
2125     void* _aaGet(void** pp, TypeInfo keyti, size_t valuesize, ...);
2126     void* _aaGetRvalue(void* p, TypeInfo keyti, size_t valuesize, ...);
2127     void* _aaIn(void* p, TypeInfo keyti);
2128     void _aaDel(void* p, TypeInfo keyti, ...);
2129     void[] _aaValues(void* p, size_t keysize, size_t valuesize);
2130     void[] _aaKeys(void* p, size_t keysize, size_t valuesize);
2131     void* _aaRehash(void** pp, TypeInfo keyti);
2132
2133     extern (D) typedef scope int delegate(void *) _dg_t;
2134     int _aaApply(void* aa, size_t keysize, _dg_t dg);
2135
2136     extern (D) typedef scope int delegate(void *, void *) _dg2_t;
2137     int _aaApply2(void* aa, size_t keysize, _dg2_t dg);
2138
2139     void* _d_assocarrayliteralT(TypeInfo_AssociativeArray ti, size_t length, ...);
2140 }
2141
2142 struct AssociativeArray(Key, Value)
2143 {
2144     void* p;
2145
2146     size_t aligntsize(size_t tsize)
2147     {
2148     // Is pointer alignment on the x64 4 bytes or 8?
2149     return (tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1);
2150     }
2151
2152     size_t length() @property { return _aaLen(p); }
2153
2154     Value[Key] rehash() @property
2155     {
2156         auto p = _aaRehash(&p, typeid(Value[Key]));
2157         return *cast(Value[Key]*)(&p);
2158     }
2159
2160     Value[] values() @property
2161     {
2162         auto a = _aaValues(p, aligntsize(Key.sizeof), Value.sizeof);
2163         return *cast(Value[]*) &a;
2164     }
2165
2166     Key[] keys() @property
2167     {
2168         auto a = _aaKeys(p, aligntsize(Key.sizeof), Value.sizeof);
2169         return *cast(Key[]*) &a;
2170     }
2171
2172     int opApply(scope int delegate(ref Key, ref Value) dg)
2173     {
2174         return _aaApply2(p, aligntsize(Key.sizeof), cast(_dg2_t)dg);
2175     }
2176
2177     int opApply(scope int delegate(ref Value) dg)
2178     {
2179         return _aaApply(p, aligntsize(Key.sizeof), cast(_dg_t)dg);
2180     }
2181
2182     int delegate(int delegate(ref Key) dg) byKey()
2183     {
2184     // Discard the Value part and just do the Key
2185     int foo(int delegate(ref Key) dg)
2186     {
2187         int byKeydg(ref Key key, ref Value value)
2188         {
2189         return dg(key);
2190         }
2191
2192         return _aaApply2(p, aligntsize(Key.sizeof), cast(_dg2_t)&byKeydg);
2193     }
2194
2195     return &foo;
2196     }
2197
2198     int delegate(int delegate(ref Value) dg) byValue()
2199     {
2200     return &opApply;
2201     }
2202
2203     Value get(Key key, lazy Value defaultValue)
2204     {
2205     auto p = key in *cast(Value[Key]*)(&p);
2206     return p ? *p : defaultValue;
2207     }
2208 }
2209
2210
2211 void clear(T)(T obj) if (is(T == class))
2212 {
2213     auto ci = obj.classinfo;
2214     auto defaultCtor =
2215         cast(void function(Object)) ci.defaultConstructor;
2216     version(none) // enforce isn't available in druntime
2217         _enforce(defaultCtor || (ci.flags & 8) == 0);
2218     immutable size = ci.init.length;
2219
2220     auto ci2 = ci;
2221     do
2222     {
2223         auto dtor = cast(void function(Object))ci2.destructor;
2224         if (dtor)
2225             dtor(obj);
2226         ci2 = ci2.base;
2227     } while (ci2)
2228
2229     auto buf = (cast(void*) obj)[0 .. size];
2230     buf[] = ci.init;
2231     if (defaultCtor)
2232         defaultCtor(obj);
2233 }
2234
2235 version(unittest) unittest
2236 {
2237    {
2238        class A { string s = "A"; this() {} }
2239        auto a = new A;
2240        a.s = "asd";
2241        clear(a);
2242        assert(a.s == "A");
2243    }
2244    {
2245        static bool destroyed = false;
2246        class B
2247        {
2248            string s = "B";
2249            this() {}
2250            ~this()
2251            {
2252                destroyed = true;
2253            }
2254        }
2255        auto a = new B;
2256        a.s = "asd";
2257        clear(a);
2258        assert(destroyed);
2259        assert(a.s == "B");
2260    }
2261    {
2262        class C
2263        {
2264            string s;
2265            this()
2266            {
2267                s = "C";
2268            }
2269        }
2270        auto a = new C;
2271        a.s = "asd";
2272        clear(a);
2273        assert(a.s == "C");
2274    }
2275 }
2276
2277 void clear(T)(ref T obj) if (is(T == struct))
2278 {
2279    static if (is(typeof(obj.__dtor())))
2280    {
2281        obj.__dtor();
2282    }
2283    auto buf = (cast(void*) &obj)[0 .. T.sizeof];
2284    auto init = (cast(void*) &T.init)[0 .. T.sizeof];
2285    buf[] = init[];
2286 }
2287
2288 version(unittest) unittest
2289 {
2290    {
2291        struct A { string s = "A";  }
2292        A a;
2293        a.s = "asd";
2294        clear(a);
2295        assert(a.s == "A");
2296    }
2297    {
2298        static bool destroyed = false;
2299        struct B
2300        {
2301            string s = "B";
2302            ~this()
2303            {
2304                destroyed = true;
2305            }
2306        }
2307        B a;
2308        a.s = "asd";
2309        clear(a);
2310        assert(destroyed);
2311        assert(a.s == "B");
2312    }
2313 }
2314
2315 void clear(T : U[n], U, size_t n)(ref T obj)
2316 {
2317     obj = T.init;
2318 }
2319
2320 version(unittest) unittest
2321 {
2322     int[2] a;
2323     a[0] = 1;
2324     a[1] = 2;
2325     clear(a);
2326     assert(a == [ 0, 0 ]);
2327 }
2328
2329 void clear(T)(ref T obj)
2330     if (!is(T == struct) && !is(T == class) && !_isStaticArray!T)
2331 {
2332     obj = T.init;
2333 }
2334
2335 template _isStaticArray(T : U[N], U, size_t N)
2336 {
2337     enum bool _isStaticArray = true;
2338 }
2339
2340 template _isStaticArray(T)
2341 {
2342     enum bool _isStaticArray = false;
2343 }
2344
2345 version(unittest) unittest
2346 {
2347    {
2348        int a = 42;
2349        clear(a);
2350        assert(a == 0);
2351    }
2352    {
2353        float a = 42;
2354        clear(a);
2355        assert(isnan(a));
2356    }
2357 }
2358
2359 version (unittest)
2360 {
2361     bool isnan(float x)
2362     {
2363         return x != x;
2364     }
2365 }
2366
2367 /**
2368  * (Property) Get the current capacity of an array.  The capacity is the number
2369  * of elements that the array can grow to before the array must be
2370  * extended/reallocated.
2371  */
2372 @property size_t capacity(T)(T[] arr)
2373 {
2374     return _d_arraysetcapacity(typeid(T[]), 0, cast(void *)&arr);
2375 }
2376
2377 /**
2378  * Try to reserve capacity for an array.  The capacity is the number of
2379  * elements that the array can grow to before the array must be
2380  * extended/reallocated.
2381  *
2382  * The return value is the new capacity of the array (which may be larger than
2383  * the requested capacity).
2384  */
2385 size_t reserve(T)(ref T[] arr, size_t newcapacity)
2386 {
2387     return _d_arraysetcapacity(typeid(T[]), newcapacity, cast(void *)&arr);
2388 }
2389
2390 /**
2391  * Assume that it is safe to append to this array.  Appends made to this array
2392  * after calling this function may append in place, even if the array was a
2393  * slice of a larger array to begin with.
2394  *
2395  * Use this only when you are sure no elements are in use beyond the array in
2396  * the memory block.  If there are, those elements could be overwritten by
2397  * appending to this array.
2398  *
2399  * Calling this function, and then using references to data located after the
2400  * given array results in undefined behavior.
2401  */
2402 void assumeSafeAppend(T)(T[] arr)
2403 {
2404     _d_arrayshrinkfit(typeid(T[]), *(cast(void[]*)&arr));
2405 }
2406
2407 version (unittest) unittest
2408 {
2409     {
2410         int[] arr;
2411         auto newcap = arr.reserve(2000);
2412         assert(newcap >= 2000);
2413         assert(newcap == arr.capacity);
2414         auto ptr = arr.ptr;
2415         foreach(i; 0..2000)
2416             arr ~= i;
2417         assert(ptr == arr.ptr);
2418         arr = arr[0..1];
2419         arr.assumeSafeAppend();
2420         arr ~= 5;
2421         assert(ptr == arr.ptr);
2422     }
2423 }
2424
2425
2426 version (none)
2427 {
2428     // enforce() copied from Phobos std.contracts for clear(), left out until
2429     // we decide whether to use it.
2430    
2431
2432     T _enforce(T, string file = __FILE__, int line = __LINE__)
2433         (T value, lazy const(char)[] msg = null)
2434     {
2435         if (!value) bailOut(file, line, msg);
2436         return value;
2437     }
2438
2439     T _enforce(T, string file = __FILE__, int line = __LINE__)
2440         (T value, scope void delegate() dg)
2441     {
2442         if (!value) dg();
2443         return value;
2444     }
2445
2446     T _enforce(T)(T value, lazy Exception ex)
2447     {
2448         if (!value) throw ex();
2449         return value;
2450     }
2451
2452     private void _bailOut(string file, int line, in char[] msg)
2453     {
2454         char[21] buf;
2455         throw new Exception(cast(string)(file ~ "(" ~ ulongToString(buf[], line) ~ "): " ~ (msg ? msg : "Enforcement failed")));
2456     }
2457 }
2458
2459
2460 /***************************************
2461  * Helper function used to see if two containers of different
2462  * types have the same contents in the same sequence.
2463  */
2464
2465 bool _ArrayEq(T1, T2)(T1[] a1, T2[] a2)
2466 {
2467     if (a1.length != a2.length)
2468     return false;
2469     foreach(i, a; a1)
2470     {   if (a != a2[i])
2471         return false;
2472     }
2473     return true;
2474 }
Note: See TracBrowser for help on using the browser.