comparison druntime/src/compiler/dmd/object_.d @ 759:d3eb054172f9

Added copy of druntime from DMD 2.020 modified for LDC.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Tue, 11 Nov 2008 01:52:37 +0100
parents
children
comparison
equal deleted inserted replaced
758:f04dde6e882c 759:d3eb054172f9
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 for use with the D Runtime Project
36 */
37
38 module object;
39
40 private
41 {
42 import stdc.string;
43 import stdc.stdlib;
44 import util.string;
45 debug(PRINTF) import stdc.stdio;
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 alias bool equals_t;
70
71 alias invariant(char)[] string;
72 alias invariant(wchar)[] wstring;
73 alias invariant(dchar)[] dstring;
74
75 /**
76 * All D class objects inherit from Object.
77 */
78 class Object
79 {
80 /**
81 * Convert Object to a human readable string.
82 */
83 string toString()
84 {
85 return this.classinfo.name;
86 }
87
88 /**
89 * Compute hash function for Object.
90 */
91 hash_t toHash()
92 {
93 // BUG: this prevents a compacting GC from working, needs to be fixed
94 return cast(hash_t)cast(void*)this;
95 }
96
97 /**
98 * Compare with another Object obj.
99 * Returns:
100 * $(TABLE
101 * $(TR $(TD this &lt; obj) $(TD &lt; 0))
102 * $(TR $(TD this == obj) $(TD 0))
103 * $(TR $(TD this &gt; obj) $(TD &gt; 0))
104 * )
105 */
106 int opCmp(Object o)
107 {
108 // BUG: this prevents a compacting GC from working, needs to be fixed
109 //return cast(int)cast(void*)this - cast(int)cast(void*)o;
110
111 throw new Exception("need opCmp for class " ~ this.classinfo.name);
112 //return this !is o;
113 }
114
115 /**
116 * Returns !=0 if this object does have the same contents as obj.
117 */
118 equals_t opEquals(Object o)
119 {
120 return this is o;
121 }
122
123 interface Monitor
124 {
125 void lock();
126 void unlock();
127 }
128
129 /**
130 * Create instance of class specified by classname.
131 * The class must either have no constructors or have
132 * a default constructor.
133 * Returns:
134 * null if failed
135 */
136 static Object factory(string classname)
137 {
138 auto ci = ClassInfo.find(classname);
139 if (ci)
140 {
141 return ci.create();
142 }
143 return null;
144 }
145 }
146
147 /**
148 * Information about an interface.
149 * When an object is accessed via an interface, an Interface* appears as the
150 * first entry in its vtbl.
151 */
152 struct Interface
153 {
154 ClassInfo classinfo; /// .classinfo for this interface (not for containing class)
155 void*[] vtbl;
156 ptrdiff_t offset; /// offset to Interface 'this' from Object 'this'
157 }
158
159 /**
160 * Runtime type information about a class. Can be retrieved for any class type
161 * or instance by using the .classinfo property.
162 * A pointer to this appears as the first entry in the class's vtbl[].
163 */
164 class ClassInfo : Object
165 {
166 byte[] init; /** class static initializer
167 * (init.length gives size in bytes of class)
168 */
169 string name; /// class name
170 void*[] vtbl; /// virtual function pointer table
171 Interface[] interfaces; /// interfaces this class implements
172 ClassInfo base; /// base class
173 void* destructor;
174 void function(Object) classInvariant;
175 uint flags;
176 // 1: // is IUnknown or is derived from IUnknown
177 // 2: // has no possible pointers into GC memory
178 // 4: // has offTi[] member
179 // 8: // has constructors
180 // 16: // has xgetMembers member
181 void* deallocator;
182 OffsetTypeInfo[] offTi;
183 void function(Object) defaultConstructor; // default Constructor
184 const(MemberInfo[]) function(in char[]) xgetMembers;
185
186 /**
187 * Search all modules for ClassInfo corresponding to classname.
188 * Returns: null if not found
189 */
190 static ClassInfo find(in char[] classname)
191 {
192 foreach (m; ModuleInfo)
193 {
194 //writefln("module %s, %d", m.name, m.localClasses.length);
195 foreach (c; m.localClasses)
196 {
197 //writefln("\tclass %s", c.name);
198 if (c.name == classname)
199 return c;
200 }
201 }
202 return null;
203 }
204
205 /**
206 * Create instance of Object represented by 'this'.
207 */
208 Object create()
209 {
210 if (flags & 8 && !defaultConstructor)
211 return null;
212 Object o = _d_newclass(this);
213 if (flags & 8 && defaultConstructor)
214 {
215 defaultConstructor(o);
216 }
217 return o;
218 }
219
220 /**
221 * Search for all members with the name 'name'.
222 * If name[] is null, return all members.
223 */
224 const(MemberInfo[]) getMembers(in char[] name)
225 {
226 if (flags & 16 && xgetMembers)
227 return xgetMembers(name);
228 return null;
229 }
230 }
231
232 /**
233 * Array of pairs giving the offset and type information for each
234 * member in an aggregate.
235 */
236 struct OffsetTypeInfo
237 {
238 size_t offset; /// Offset of member from start of object
239 TypeInfo ti; /// TypeInfo for this member
240 }
241
242 /**
243 * Runtime type information about a type.
244 * Can be retrieved for any type using a
245 * <a href="../expression.html#typeidexpression">TypeidExpression</a>.
246 */
247 class TypeInfo
248 {
249 override hash_t toHash()
250 {
251 hash_t hash;
252
253 foreach (char c; this.toString())
254 hash = hash * 9 + c;
255 return hash;
256 }
257
258 override int opCmp(Object o)
259 {
260 if (this is o)
261 return 0;
262 TypeInfo ti = cast(TypeInfo)o;
263 if (ti is null)
264 return 1;
265 return dstrcmp(this.toString(), ti.toString());
266 }
267
268 override equals_t opEquals(Object o)
269 {
270 /* TypeInfo instances are singletons, but duplicates can exist
271 * across DLL's. Therefore, comparing for a name match is
272 * sufficient.
273 */
274 if (this is o)
275 return true;
276 TypeInfo ti = cast(TypeInfo)o;
277 return ti && this.toString() == ti.toString();
278 }
279
280 /// Returns a hash of the instance of a type.
281 hash_t getHash(in void* p) { return cast(hash_t)p; }
282
283 /// Compares two instances for equality.
284 equals_t equals(in void* p1, in void* p2) { return p1 == p2; }
285
286 /// Compares two instances for &lt;, ==, or &gt;.
287 int compare(in void* p1, in void* p2) { return 0; }
288
289 /// Returns size of the type.
290 size_t tsize() { return 0; }
291
292 /// Swaps two instances of the type.
293 void swap(void* p1, void* p2)
294 {
295 size_t n = tsize();
296 for (size_t i = 0; i < n; i++)
297 {
298 byte t = (cast(byte *)p1)[i];
299 (cast(byte*)p1)[i] = (cast(byte*)p2)[i];
300 (cast(byte*)p2)[i] = t;
301 }
302 }
303
304 /// Get TypeInfo for 'next' type, as defined by what kind of type this is,
305 /// null if none.
306 TypeInfo next() { return null; }
307
308 /// Return default initializer, null if default initialize to 0
309 void[] init() { return null; }
310
311 /// Get flags for type: 1 means GC should scan for pointers
312 uint flags() { return 0; }
313
314 /// Get type information on the contents of the type; null if not available
315 OffsetTypeInfo[] offTi() { return null; }
316 /// Run the destructor on the object and all its sub-objects
317 void destroy(void* p) {}
318 /// Run the postblit on the object and all its sub-objects
319 void postblit(void* p) {}
320 }
321
322 class TypeInfo_Typedef : TypeInfo
323 {
324 override string toString() { return name; }
325
326 override equals_t opEquals(Object o)
327 {
328 TypeInfo_Typedef c;
329 return this is o ||
330 ((c = cast(TypeInfo_Typedef)o) !is null &&
331 this.name == c.name &&
332 this.base == c.base);
333 }
334
335 override hash_t getHash(in void* p) { return base.getHash(p); }
336 override equals_t equals(in void* p1, in void* p2) { return base.equals(p1, p2); }
337 override int compare(in void* p1, in void* p2) { return base.compare(p1, p2); }
338 override size_t tsize() { return base.tsize(); }
339 override void swap(void* p1, void* p2) { return base.swap(p1, p2); }
340
341 override TypeInfo next() { return base.next(); }
342 override uint flags() { return base.flags(); }
343 override void[] init() { return m_init.length ? m_init : base.init(); }
344
345 TypeInfo base;
346 string name;
347 void[] m_init;
348 }
349
350 class TypeInfo_Enum : TypeInfo_Typedef
351 {
352
353 }
354
355 class TypeInfo_Pointer : TypeInfo
356 {
357 override string toString() { return m_next.toString() ~ "*"; }
358
359 override equals_t opEquals(Object o)
360 {
361 TypeInfo_Pointer c;
362 return this is o ||
363 ((c = cast(TypeInfo_Pointer)o) !is null &&
364 this.m_next == c.m_next);
365 }
366
367 override hash_t getHash(in void* p)
368 {
369 return cast(hash_t)*cast(void**)p;
370 }
371
372 override equals_t equals(in void* p1, in void* p2)
373 {
374 return *cast(void**)p1 == *cast(void**)p2;
375 }
376
377 override int compare(in void* p1, in void* p2)
378 {
379 if (*cast(void**)p1 < *cast(void**)p2)
380 return -1;
381 else if (*cast(void**)p1 > *cast(void**)p2)
382 return 1;
383 else
384 return 0;
385 }
386
387 override size_t tsize()
388 {
389 return (void*).sizeof;
390 }
391
392 override void swap(void* p1, void* p2)
393 {
394 void* tmp = *cast(void**)p1;
395 *cast(void**)p1 = *cast(void**)p2;
396 *cast(void**)p2 = tmp;
397 }
398
399 override TypeInfo next() { return m_next; }
400 override uint flags() { return 1; }
401
402 TypeInfo m_next;
403 }
404
405 class TypeInfo_Array : TypeInfo
406 {
407 override string toString() { return value.toString() ~ "[]"; }
408
409 override equals_t opEquals(Object o)
410 {
411 TypeInfo_Array c;
412 return this is o ||
413 ((c = cast(TypeInfo_Array)o) !is null &&
414 this.value == c.value);
415 }
416
417 override hash_t getHash(in void* p)
418 {
419 size_t sz = value.tsize();
420 hash_t hash = 0;
421 void[] a = *cast(void[]*)p;
422 for (size_t i = 0; i < a.length; i++)
423 hash += value.getHash(a.ptr + i * sz);
424 return hash;
425 }
426
427 override equals_t equals(in void* p1, in void* p2)
428 {
429 void[] a1 = *cast(void[]*)p1;
430 void[] a2 = *cast(void[]*)p2;
431 if (a1.length != a2.length)
432 return false;
433 size_t sz = value.tsize();
434 for (size_t i = 0; i < a1.length; i++)
435 {
436 if (!value.equals(a1.ptr + i * sz, a2.ptr + i * sz))
437 return false;
438 }
439 return true;
440 }
441
442 override int compare(in void* p1, in void* p2)
443 {
444 void[] a1 = *cast(void[]*)p1;
445 void[] a2 = *cast(void[]*)p2;
446 size_t sz = value.tsize();
447 size_t len = a1.length;
448
449 if (a2.length < len)
450 len = a2.length;
451 for (size_t u = 0; u < len; u++)
452 {
453 int result = value.compare(a1.ptr + u * sz, a2.ptr + u * sz);
454 if (result)
455 return result;
456 }
457 return cast(int)a1.length - cast(int)a2.length;
458 }
459
460 override size_t tsize()
461 {
462 return (void[]).sizeof;
463 }
464
465 override void swap(void* p1, void* p2)
466 {
467 void[] tmp = *cast(void[]*)p1;
468 *cast(void[]*)p1 = *cast(void[]*)p2;
469 *cast(void[]*)p2 = tmp;
470 }
471
472 TypeInfo value;
473
474 override TypeInfo next()
475 {
476 return value;
477 }
478
479 override uint flags() { return 1; }
480 }
481
482 class TypeInfo_StaticArray : TypeInfo
483 {
484 override string toString()
485 {
486 char[10] tmp = void;
487 return cast(string)(value.toString() ~ "[" ~ tmp.intToString(len) ~ "]");
488 }
489
490 override equals_t opEquals(Object o)
491 {
492 TypeInfo_StaticArray c;
493 return this is o ||
494 ((c = cast(TypeInfo_StaticArray)o) !is null &&
495 this.len == c.len &&
496 this.value == c.value);
497 }
498
499 override hash_t getHash(in void* p)
500 {
501 size_t sz = value.tsize();
502 hash_t hash = 0;
503 for (size_t i = 0; i < len; i++)
504 hash += value.getHash(p + i * sz);
505 return hash;
506 }
507
508 override equals_t equals(in void* p1, in void* p2)
509 {
510 size_t sz = value.tsize();
511
512 for (size_t u = 0; u < len; u++)
513 {
514 if (!value.equals(p1 + u * sz, p2 + u * sz))
515 return false;
516 }
517 return true;
518 }
519
520 override int compare(in void* p1, in void* p2)
521 {
522 size_t sz = value.tsize();
523
524 for (size_t u = 0; u < len; u++)
525 {
526 int result = value.compare(p1 + u * sz, p2 + u * sz);
527 if (result)
528 return result;
529 }
530 return 0;
531 }
532
533 override size_t tsize()
534 {
535 return len * value.tsize();
536 }
537
538 override void swap(void* p1, void* p2)
539 {
540 void* tmp;
541 size_t sz = value.tsize();
542 ubyte[16] buffer;
543 void* pbuffer;
544
545 if (sz < buffer.sizeof)
546 tmp = buffer.ptr;
547 else
548 tmp = pbuffer = (new void[sz]).ptr;
549
550 for (size_t u = 0; u < len; u += sz)
551 { size_t o = u * sz;
552 memcpy(tmp, p1 + o, sz);
553 memcpy(p1 + o, p2 + o, sz);
554 memcpy(p2 + o, tmp, sz);
555 }
556 if (pbuffer)
557 delete pbuffer;
558 }
559
560 override void[] init() { return value.init(); }
561 override TypeInfo next() { return value; }
562 override uint flags() { return value.flags(); }
563
564 override void destroy(void* p)
565 {
566 auto sz = value.tsize();
567 p += sz * len;
568 foreach (i; 0 .. len)
569 {
570 p -= sz;
571 value.destroy(p);
572 }
573 }
574
575 override void postblit(void* p)
576 {
577 auto sz = value.tsize();
578 foreach (i; 0 .. len)
579 {
580 value.postblit(p);
581 p += sz;
582 }
583 }
584
585 TypeInfo value;
586 size_t len;
587 }
588
589 class TypeInfo_AssociativeArray : TypeInfo
590 {
591 override string toString()
592 {
593 return cast(string)(next.toString() ~ "[" ~ key.toString() ~ "]");
594 }
595
596 override equals_t opEquals(Object o)
597 {
598 TypeInfo_AssociativeArray c;
599 return this is o ||
600 ((c = cast(TypeInfo_AssociativeArray)o) !is null &&
601 this.key == c.key &&
602 this.value == c.value);
603 }
604
605 // BUG: need to add the rest of the functions
606
607 override size_t tsize()
608 {
609 return (char[int]).sizeof;
610 }
611
612 override TypeInfo next() { return value; }
613 override uint flags() { return 1; }
614
615 TypeInfo value;
616 TypeInfo key;
617 }
618
619 class TypeInfo_Function : TypeInfo
620 {
621 override string toString()
622 {
623 return cast(string)(next.toString() ~ "()");
624 }
625
626 override equals_t opEquals(Object o)
627 {
628 TypeInfo_Function c;
629 return this is o ||
630 ((c = cast(TypeInfo_Function)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 return 0; // no size for functions
639 }
640
641 TypeInfo next;
642 }
643
644 class TypeInfo_Delegate : TypeInfo
645 {
646 override string toString()
647 {
648 return cast(string)(next.toString() ~ " delegate()");
649 }
650
651 override equals_t opEquals(Object o)
652 {
653 TypeInfo_Delegate c;
654 return this is o ||
655 ((c = cast(TypeInfo_Delegate)o) !is null &&
656 this.next == c.next);
657 }
658
659 // BUG: need to add the rest of the functions
660
661 override size_t tsize()
662 {
663 alias int delegate() dg;
664 return dg.sizeof;
665 }
666
667 override uint flags() { return 1; }
668
669 TypeInfo next;
670 }
671
672 class TypeInfo_Class : TypeInfo
673 {
674 override string toString() { return info.name; }
675
676 override equals_t opEquals(Object o)
677 {
678 TypeInfo_Class c;
679 return this is o ||
680 ((c = cast(TypeInfo_Class)o) !is null &&
681 this.info.name == c.classinfo.name);
682 }
683
684 override hash_t getHash(in void* p)
685 {
686 Object o = *cast(Object*)p;
687 return o ? o.toHash() : 0;
688 }
689
690 override equals_t equals(in void* p1, in void* p2)
691 {
692 Object o1 = *cast(Object*)p1;
693 Object o2 = *cast(Object*)p2;
694
695 return (o1 is o2) || (o1 && o1.opEquals(o2));
696 }
697
698 override int compare(in void* p1, in void* p2)
699 {
700 Object o1 = *cast(Object*)p1;
701 Object o2 = *cast(Object*)p2;
702 int c = 0;
703
704 // Regard null references as always being "less than"
705 if (o1 !is o2)
706 {
707 if (o1)
708 {
709 if (!o2)
710 c = 1;
711 else
712 c = o1.opCmp(o2);
713 }
714 else
715 c = -1;
716 }
717 return c;
718 }
719
720 override size_t tsize()
721 {
722 return Object.sizeof;
723 }
724
725 override uint flags() { return 1; }
726
727 override OffsetTypeInfo[] offTi()
728 {
729 return (info.flags & 4) ? info.offTi : null;
730 }
731
732 ClassInfo info;
733 }
734
735 class TypeInfo_Interface : TypeInfo
736 {
737 override string toString() { return info.name; }
738
739 override equals_t opEquals(Object o)
740 {
741 TypeInfo_Interface c;
742 return this is o ||
743 ((c = cast(TypeInfo_Interface)o) !is null &&
744 this.info.name == c.classinfo.name);
745 }
746
747 override hash_t getHash(in void* p)
748 {
749 Interface* pi = **cast(Interface ***)*cast(void**)p;
750 Object o = cast(Object)(*cast(void**)p - pi.offset);
751 assert(o);
752 return o.toHash();
753 }
754
755 override equals_t equals(in void* p1, in void* p2)
756 {
757 Interface* pi = **cast(Interface ***)*cast(void**)p1;
758 Object o1 = cast(Object)(*cast(void**)p1 - pi.offset);
759 pi = **cast(Interface ***)*cast(void**)p2;
760 Object o2 = cast(Object)(*cast(void**)p2 - pi.offset);
761
762 return o1 == o2 || (o1 && o1.opCmp(o2) == 0);
763 }
764
765 override int compare(in void* p1, in void* p2)
766 {
767 Interface* pi = **cast(Interface ***)*cast(void**)p1;
768 Object o1 = cast(Object)(*cast(void**)p1 - pi.offset);
769 pi = **cast(Interface ***)*cast(void**)p2;
770 Object o2 = cast(Object)(*cast(void**)p2 - pi.offset);
771 int c = 0;
772
773 // Regard null references as always being "less than"
774 if (o1 != o2)
775 {
776 if (o1)
777 {
778 if (!o2)
779 c = 1;
780 else
781 c = o1.opCmp(o2);
782 }
783 else
784 c = -1;
785 }
786 return c;
787 }
788
789 override size_t tsize()
790 {
791 return Object.sizeof;
792 }
793
794 override uint flags() { return 1; }
795
796 ClassInfo info;
797 }
798
799 class TypeInfo_Struct : TypeInfo
800 {
801 override string toString() { return name; }
802
803 override equals_t opEquals(Object o)
804 {
805 TypeInfo_Struct s;
806 return this is o ||
807 ((s = cast(TypeInfo_Struct)o) !is null &&
808 this.name == s.name &&
809 this.init.length == s.init.length);
810 }
811
812 override hash_t getHash(in void* p)
813 {
814 assert(p);
815 if (xtoHash)
816 {
817 debug(PRINTF) printf("getHash() using xtoHash\n");
818 return (*xtoHash)(p);
819 }
820 else
821 {
822 hash_t h;
823 debug(PRINTF) printf("getHash() using default hash\n");
824 // A sorry hash algorithm.
825 // Should use the one for strings.
826 // BUG: relies on the GC not moving objects
827 auto q = cast(const(ubyte)*)p;
828 for (size_t i = 0; i < init.length; i++)
829 {
830 h = h * 9 + *q;
831 q++;
832 }
833 return h;
834 }
835 }
836
837 override equals_t equals(in void* p1, in void* p2)
838 {
839 if (p1 == p2)
840 return true;
841 else if (!p1 || !p2)
842 return false;
843 else if (xopEquals)
844 return (*xopEquals)(p1, p2);
845 else
846 // BUG: relies on the GC not moving objects
847 return memcmp(p1, p2, init.length) == 0;
848 }
849
850 override int compare(in void* p1, in void* p2)
851 {
852 // Regard null references as always being "less than"
853 if (p1 != p2)
854 {
855 if (p1)
856 {
857 if (!p2)
858 return true;
859 else if (xopCmp)
860 return (*xopCmp)(p2, p1);
861 else
862 // BUG: relies on the GC not moving objects
863 return memcmp(p1, p2, init.length);
864 }
865 else
866 return -1;
867 }
868 return 0;
869 }
870
871 override size_t tsize()
872 {
873 return init.length;
874 }
875
876 override void[] init() { return m_init; }
877
878 override uint flags() { return m_flags; }
879
880 override void destroy(void* p)
881 {
882 if (xdtor)
883 (*xdtor)(p);
884 }
885
886 override void postblit(void* p)
887 {
888 if (xpostblit)
889 (*xpostblit)(p);
890 }
891
892 string name;
893 void[] m_init; // initializer; init.ptr == null if 0 initialize
894
895 hash_t function(in void*) xtoHash;
896 equals_t function(in void*, in void*) xopEquals;
897 int function(in void*, in void*) xopCmp;
898 char[] function(in void*) xtoString;
899
900 uint m_flags;
901
902 const(MemberInfo[]) function(in char[]) xgetMembers;
903 void function(void*) xdtor;
904 void function(void*) xpostblit;
905 }
906
907 class TypeInfo_Tuple : TypeInfo
908 {
909 TypeInfo[] elements;
910
911 override string toString()
912 {
913 string s = "(";
914 foreach (i, element; elements)
915 {
916 if (i)
917 s ~= ',';
918 s ~= element.toString();
919 }
920 s ~= ")";
921 return s;
922 }
923
924 override equals_t opEquals(Object o)
925 {
926 if (this is o)
927 return true;
928
929 auto t = cast(TypeInfo_Tuple)o;
930 if (t && elements.length == t.elements.length)
931 {
932 for (size_t i = 0; i < elements.length; i++)
933 {
934 if (elements[i] != t.elements[i])
935 return false;
936 }
937 return true;
938 }
939 return false;
940 }
941
942 override hash_t getHash(in void* p)
943 {
944 assert(0);
945 }
946
947 override equals_t equals(in void* p1, in void* p2)
948 {
949 assert(0);
950 }
951
952 override int compare(in void* p1, in void* p2)
953 {
954 assert(0);
955 }
956
957 override size_t tsize()
958 {
959 assert(0);
960 }
961
962 override void swap(void* p1, void* p2)
963 {
964 assert(0);
965 }
966
967 override void destroy(void* p)
968 {
969 assert(0);
970 }
971
972 override void postblit(void* p)
973 {
974 assert(0);
975 }
976 }
977
978 class TypeInfo_Const : TypeInfo
979 {
980 override string toString()
981 {
982 return cast(string) ("const(" ~ base.toString() ~ ")");
983 }
984
985 override equals_t opEquals(Object o) { return base.opEquals(o); }
986 override hash_t getHash(in void *p) { return base.getHash(p); }
987 override equals_t equals(in void *p1, in void *p2) { return base.equals(p1, p2); }
988 override int compare(in void *p1, in void *p2) { return base.compare(p1, p2); }
989 override size_t tsize() { return base.tsize(); }
990 override void swap(void *p1, void *p2) { return base.swap(p1, p2); }
991
992 override TypeInfo next() { return base.next(); }
993 override uint flags() { return base.flags(); }
994 override void[] init() { return base.init(); }
995
996 TypeInfo base;
997 }
998
999 class TypeInfo_Invariant : TypeInfo_Const
1000 {
1001 override string toString()
1002 {
1003 return cast(string) ("invariant(" ~ base.toString() ~ ")");
1004 }
1005 }
1006
1007 abstract class MemberInfo
1008 {
1009 string name();
1010 }
1011
1012 class MemberInfo_field : MemberInfo
1013 {
1014 this(string name, TypeInfo ti, size_t offset)
1015 {
1016 m_name = name;
1017 m_typeinfo = ti;
1018 m_offset = offset;
1019 }
1020
1021 override string name() { return m_name; }
1022 TypeInfo typeInfo() { return m_typeinfo; }
1023 size_t offset() { return m_offset; }
1024
1025 string m_name;
1026 TypeInfo m_typeinfo;
1027 size_t m_offset;
1028 }
1029
1030 class MemberInfo_function : MemberInfo
1031 {
1032 this(string name, TypeInfo ti, void* fp, uint flags)
1033 {
1034 m_name = name;
1035 m_typeinfo = ti;
1036 m_fp = fp;
1037 m_flags = flags;
1038 }
1039
1040 override string name() { return m_name; }
1041 TypeInfo typeInfo() { return m_typeinfo; }
1042 void* fp() { return m_fp; }
1043 uint flags() { return m_flags; }
1044
1045 string m_name;
1046 TypeInfo m_typeinfo;
1047 void* m_fp;
1048 uint m_flags;
1049 }
1050
1051
1052 ///////////////////////////////////////////////////////////////////////////////
1053 // Throwable
1054 ///////////////////////////////////////////////////////////////////////////////
1055
1056
1057 class Throwable : Object
1058 {
1059 interface TraceInfo
1060 {
1061 int opApply(int delegate(inout char[]));
1062 }
1063
1064 string msg;
1065 string file;
1066 size_t line;
1067 TraceInfo info;
1068 Throwable next;
1069
1070 this(string msg, Throwable next = null)
1071 {
1072 this.msg = msg;
1073 this.next = next;
1074 this.info = traceContext();
1075 }
1076
1077 this(string msg, string file, size_t line, Throwable next = null)
1078 {
1079 this(msg, next);
1080 this.file = file;
1081 this.line = line;
1082 this.info = traceContext();
1083 }
1084
1085 override string toString()
1086 {
1087 char[10] tmp = void;
1088 char[] buf;
1089
1090 for (Throwable e = this; e !is null; e = e.next)
1091 {
1092 if (e.file)
1093 {
1094 buf ~= e.classinfo.name ~ "@" ~ e.file ~ "(" ~ tmp.intToString(e.line) ~ "): " ~ e.msg;
1095 }
1096 else
1097 {
1098 buf ~= e.classinfo.name ~ ": " ~ e.msg;
1099 }
1100 if (e.info)
1101 {
1102 buf ~= "\n----------------";
1103 foreach (t; e.info)
1104 buf ~= "\n" ~ t;
1105 }
1106 if (e.next)
1107 buf ~= "\n";
1108 }
1109 return cast(string) buf;
1110 }
1111 }
1112
1113
1114 alias Throwable.TraceInfo function(void* ptr = null) TraceHandler;
1115 private TraceHandler traceHandler = null;
1116
1117
1118 /**
1119 * Overrides the default trace hander with a user-supplied version.
1120 *
1121 * Params:
1122 * h = The new trace handler. Set to null to use the default handler.
1123 */
1124 extern (C) void rt_setTraceHandler(TraceHandler h)
1125 {
1126 traceHandler = h;
1127 }
1128
1129
1130 /**
1131 * This function will be called when an exception is constructed. The
1132 * user-supplied trace handler will be called if one has been supplied,
1133 * otherwise no trace will be generated.
1134 *
1135 * Params:
1136 * ptr = A pointer to the location from which to generate the trace, or null
1137 * if the trace should be generated from within the trace handler
1138 * itself.
1139 *
1140 * Returns:
1141 * An object describing the current calling context or null if no handler is
1142 * supplied.
1143 */
1144 Throwable.TraceInfo traceContext(void* ptr = null)
1145 {
1146 if (traceHandler is null)
1147 return null;
1148 return traceHandler(ptr);
1149 }
1150
1151
1152 class Exception : Throwable
1153 {
1154 this(string msg, Throwable next = null)
1155 {
1156 super(msg, next);
1157 }
1158
1159 this(string msg, string file, size_t line, Throwable next = null)
1160 {
1161 super(msg, file, line, next);
1162 }
1163 }
1164
1165
1166 class Error : Throwable
1167 {
1168 this(string msg, Throwable next = null)
1169 {
1170 super(msg, next);
1171 }
1172
1173 this(string msg, string file, size_t line, Throwable next = null)
1174 {
1175 super(msg, file, line, next);
1176 }
1177 }
1178
1179
1180 ///////////////////////////////////////////////////////////////////////////////
1181 // ModuleInfo
1182 ///////////////////////////////////////////////////////////////////////////////
1183
1184
1185 enum
1186 {
1187 MIctorstart = 1, // we've started constructing it
1188 MIctordone = 2, // finished construction
1189 MIstandalone = 4, // module ctor does not depend on other module
1190 // ctors being done first
1191 MIhasictor = 8, // has ictor member
1192 }
1193
1194
1195 class ModuleInfo
1196 {
1197 string name;
1198 ModuleInfo[] importedModules;
1199 ClassInfo[] localClasses;
1200 uint flags;
1201
1202 void function() ctor; // module static constructor (order dependent)
1203 void function() dtor; // module static destructor
1204 void function() unitTest; // module unit tests
1205
1206 void* xgetMembers; // module getMembers() function
1207
1208 void function() ictor; // module static constructor (order independent)
1209
1210 static int opApply(int delegate(inout ModuleInfo) dg)
1211 {
1212 int ret = 0;
1213
1214 foreach (m; _moduleinfo_array)
1215 {
1216 ret = dg(m);
1217 if (ret)
1218 break;
1219 }
1220 return ret;
1221 }
1222 }
1223
1224
1225 // Windows: this gets initialized by minit.asm
1226 // linux: this gets initialized in _moduleCtor()
1227 extern (C) ModuleInfo[] _moduleinfo_array;
1228
1229
1230 version (linux)
1231 {
1232 // This linked list is created by a compiler generated function inserted
1233 // into the .ctor list by the compiler.
1234 struct ModuleReference
1235 {
1236 ModuleReference* next;
1237 ModuleInfo mod;
1238 }
1239
1240 extern (C) ModuleReference* _Dmodule_ref; // start of linked list
1241 }
1242
1243 ModuleInfo[] _moduleinfo_dtors;
1244 uint _moduleinfo_dtors_i;
1245
1246 // Register termination function pointers
1247 extern (C) int _fatexit(void*);
1248
1249 /**
1250 * Initialize the modules.
1251 */
1252
1253 extern (C) void _moduleCtor()
1254 {
1255 debug(PRINTF) printf("_moduleCtor()\n");
1256 version (linux)
1257 {
1258 int len = 0;
1259 ModuleReference *mr;
1260
1261 for (mr = _Dmodule_ref; mr; mr = mr.next)
1262 len++;
1263 _moduleinfo_array = new ModuleInfo[len];
1264 len = 0;
1265 for (mr = _Dmodule_ref; mr; mr = mr.next)
1266 { _moduleinfo_array[len] = mr.mod;
1267 len++;
1268 }
1269 }
1270
1271 version (Windows)
1272 {
1273 // Ensure module destructors also get called on program termination
1274 //_fatexit(&_STD_moduleDtor);
1275 }
1276
1277 _moduleinfo_dtors = new ModuleInfo[_moduleinfo_array.length];
1278 debug(PRINTF) printf("_moduleinfo_dtors = x%x\n", cast(void*)_moduleinfo_dtors);
1279 _moduleIndependentCtors();
1280 _moduleCtor2(_moduleinfo_array, 0);
1281 }
1282
1283 extern (C) void _moduleIndependentCtors()
1284 {
1285 debug(PRINTF) printf("_moduleIndependentCtors()\n");
1286 foreach (m; _moduleinfo_array)
1287 {
1288 if (m && m.flags & MIhasictor && m.ictor)
1289 {
1290 (*m.ictor)();
1291 }
1292 }
1293 }
1294
1295 void _moduleCtor2(ModuleInfo[] mi, int skip)
1296 {
1297 debug(PRINTF) printf("_moduleCtor2(): %d modules\n", mi.length);
1298 for (uint i = 0; i < mi.length; i++)
1299 {
1300 ModuleInfo m = mi[i];
1301
1302 debug(PRINTF) printf("\tmodule[%d] = '%p'\n", i, m);
1303 if (!m)
1304 continue;
1305 debug(PRINTF) printf("\tmodule[%d] = '%.*s'\n", i, m.name);
1306 if (m.flags & MIctordone)
1307 continue;
1308 debug(PRINTF) printf("\tmodule[%d] = '%.*s', m = x%x\n", i, m.name, m);
1309
1310 if (m.ctor || m.dtor)
1311 {
1312 if (m.flags & MIctorstart)
1313 { if (skip || m.flags & MIstandalone)
1314 continue;
1315 throw new Exception("Cyclic dependency in module " ~ m.name);
1316 }
1317
1318 m.flags |= MIctorstart;
1319 _moduleCtor2(m.importedModules, 0);
1320 if (m.ctor)
1321 (*m.ctor)();
1322 m.flags &= ~MIctorstart;
1323 m.flags |= MIctordone;
1324
1325 // Now that construction is done, register the destructor
1326 //printf("\tadding module dtor x%x\n", m);
1327 assert(_moduleinfo_dtors_i < _moduleinfo_dtors.length);
1328 _moduleinfo_dtors[_moduleinfo_dtors_i++] = m;
1329 }
1330 else
1331 {
1332 m.flags |= MIctordone;
1333 _moduleCtor2(m.importedModules, 1);
1334 }
1335 }
1336 }
1337
1338 /**
1339 * Destruct the modules.
1340 */
1341
1342 // Starting the name with "_STD" means under linux a pointer to the
1343 // function gets put in the .dtors segment.
1344
1345 extern (C) void _moduleDtor()
1346 {
1347 debug(PRINTF) printf("_moduleDtor(): %d modules\n", _moduleinfo_dtors_i);
1348
1349 for (uint i = _moduleinfo_dtors_i; i-- != 0;)
1350 {
1351 ModuleInfo m = _moduleinfo_dtors[i];
1352
1353 debug(PRINTF) printf("\tmodule[%d] = '%.*s', x%x\n", i, m.name, m);
1354 if (m.dtor)
1355 {
1356 (*m.dtor)();
1357 }
1358 }
1359 debug(PRINTF) printf("_moduleDtor() done\n");
1360 }
1361
1362 ///////////////////////////////////////////////////////////////////////////////
1363 // Monitor
1364 ///////////////////////////////////////////////////////////////////////////////
1365
1366 alias Object.Monitor IMonitor;
1367 alias void delegate(Object) DEvent;
1368
1369 // NOTE: The dtor callback feature is only supported for monitors that are not
1370 // supplied by the user. The assumption is that any object with a user-
1371 // supplied monitor may have special storage or lifetime requirements and
1372 // that as a result, storing references to local objects within Monitor
1373 // may not be safe or desirable. Thus, devt is only valid if impl is
1374 // null.
1375 struct Monitor
1376 {
1377 IMonitor impl;
1378 /* internal */
1379 DEvent[] devt;
1380 /* stuff */
1381 }
1382
1383 Monitor* getMonitor(Object h)
1384 {
1385 return cast(Monitor*) (cast(void**) h)[1];
1386 }
1387
1388 void setMonitor(Object h, Monitor* m)
1389 {
1390 (cast(void**) h)[1] = m;
1391 }
1392
1393 extern (C) void _d_monitor_create(Object);
1394 extern (C) void _d_monitor_destroy(Object);
1395 extern (C) void _d_monitor_lock(Object);
1396 extern (C) int _d_monitor_unlock(Object);
1397
1398 extern (C) void _d_monitordelete(Object h, bool det)
1399 {
1400 Monitor* m = getMonitor(h);
1401
1402 if (m !is null)
1403 {
1404 IMonitor i = m.impl;
1405 if (i is null)
1406 {
1407 _d_monitor_devt(m, h);
1408 _d_monitor_destroy(h);
1409 setMonitor(h, null);
1410 return;
1411 }
1412 if (det && (cast(void*) i) !is (cast(void*) h))
1413 delete i;
1414 setMonitor(h, null);
1415 }
1416 }
1417
1418 extern (C) void _d_monitorenter(Object h)
1419 {
1420 Monitor* m = getMonitor(h);
1421
1422 if (m is null)
1423 {
1424 _d_monitor_create(h);
1425 m = getMonitor(h);
1426 }
1427
1428 IMonitor i = m.impl;
1429
1430 if (i is null)
1431 {
1432 _d_monitor_lock(h);
1433 return;
1434 }
1435 i.lock();
1436 }
1437
1438 extern (C) void _d_monitorexit(Object h)
1439 {
1440 Monitor* m = getMonitor(h);
1441 IMonitor i = m.impl;
1442
1443 if (i is null)
1444 {
1445 _d_monitor_unlock(h);
1446 return;
1447 }
1448 i.unlock();
1449 }
1450
1451 extern (C) void _d_monitor_devt(Monitor* m, Object h)
1452 {
1453 if (m.devt.length)
1454 {
1455 DEvent[] devt;
1456
1457 synchronized (h)
1458 {
1459 devt = m.devt;
1460 m.devt = null;
1461 }
1462 foreach (v; devt)
1463 {
1464 if (v)
1465 v(h);
1466 }
1467 free(devt.ptr);
1468 }
1469 }
1470
1471 extern (C) void rt_attachDisposeEvent(Object h, DEvent e)
1472 {
1473 synchronized (h)
1474 {
1475 Monitor* m = getMonitor(h);
1476 assert(m.impl is null);
1477
1478 foreach (inout v; m.devt)
1479 {
1480 if (v is null || v == e)
1481 {
1482 v = e;
1483 return;
1484 }
1485 }
1486
1487 auto len = m.devt.length + 4; // grow by 4 elements
1488 auto pos = m.devt.length; // insert position
1489 auto p = realloc(m.devt.ptr, DEvent.sizeof * len);
1490 if (!p)
1491 onOutOfMemoryError();
1492 m.devt = (cast(DEvent*)p)[0 .. len];
1493 m.devt[pos+1 .. len] = null;
1494 m.devt[pos] = e;
1495 }
1496 }
1497
1498 extern (C) void rt_detachDisposeEvent(Object h, DEvent e)
1499 {
1500 synchronized (h)
1501 {
1502 Monitor* m = getMonitor(h);
1503 assert(m.impl is null);
1504
1505 foreach (p, v; m.devt)
1506 {
1507 if (v == e)
1508 {
1509 memmove(&m.devt[p],
1510 &m.devt[p+1],
1511 (m.devt.length - p - 1) * DEvent.sizeof);
1512 m.devt[$ - 1] = null;
1513 return;
1514 }
1515 }
1516 }
1517 }