comparison druntime/src/compiler/ldc/genobj.d @ 1458:e0b2d67cfe7c

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