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