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.
6 * This module is implicitly imported.
12 * Copyright (C) 2004-2007 by Digital Mars, www.digitalmars.com
13 * Written by Walter Bright
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.
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
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
35 * Modified by Sean Kelly for use with the D Runtime Project
45 debug(PRINTF) import stdc.stdio;
47 extern (C) void onOutOfMemoryError();
48 extern (C) Object _d_newclass(ClassInfo ci);
51 // NOTE: For some reason, this declaration method doesn't work
52 // in this particular file (and this file only). It must
54 //alias typeof(int.sizeof) size_t;
55 //alias typeof(cast(void*)0 - cast(void*)0) ptrdiff_t;
72 alias wchar[] wstring;
73 alias dchar[] dstring;
76 * All D class objects inherit from Object.
81 * Convert Object to a human readable string.
85 return this.classinfo.name;
89 * Compute hash function for Object.
93 // BUG: this prevents a compacting GC from working, needs to be fixed
94 return cast(hash_t)cast(void*)this;
98 * Compare with another Object obj.
101 * $(TR $(TD this < obj) $(TD < 0))
102 * $(TR $(TD this == obj) $(TD 0))
103 * $(TR $(TD this > obj) $(TD > 0))
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;
111 throw new Exception("need opCmp for class " ~ this.classinfo.name);
116 * Returns !=0 if this object does have the same contents as obj.
118 equals_t opEquals(Object o)
131 * Information about an interface.
132 * When an object is accessed via an interface, an Interface* appears as the
133 * first entry in its vtbl.
137 ClassInfo classinfo; /// .classinfo for this interface (not for containing class)
139 ptrdiff_t offset; /// offset to Interface 'this' from Object 'this'
143 * Runtime type information about a class. Can be retrieved for any class type
144 * or instance by using the .classinfo property.
145 * A pointer to this appears as the first entry in the class's vtbl[].
147 class ClassInfo : Object
149 byte[] init; /** class static initializer
150 * (init.length gives size in bytes of class)
152 string name; /// class name
153 void*[] vtbl; /// virtual function pointer table
154 Interface[] interfaces; /// interfaces this class implements
155 ClassInfo base; /// base class
157 void function(Object) classInvariant;
159 // 1: // is IUnknown or is derived from IUnknown
160 // 2: // has no possible pointers into GC memory
161 // 4: // has offTi[] member
162 // 8: // has constructors
164 OffsetTypeInfo[] offTi;
165 void function(Object) defaultConstructor; // default Constructor
168 * Search all modules for ClassInfo corresponding to classname.
169 * Returns: null if not found
171 static ClassInfo find(in char[] classname)
173 foreach (m; ModuleInfo)
175 //writefln("module %s, %d", m.name, m.localClasses.length);
176 foreach (c; m.localClasses)
178 //writefln("\tclass %s", c.name);
179 if (c.name == classname)
187 * Create instance of Object represented by 'this'.
191 if (flags & 8 && !defaultConstructor)
193 Object o = _d_newclass(this);
194 if (flags & 8 && defaultConstructor)
196 defaultConstructor(o);
203 * Array of pairs giving the offset and type information for each
204 * member in an aggregate.
206 struct OffsetTypeInfo
208 size_t offset; /// Offset of member from start of object
209 TypeInfo ti; /// TypeInfo for this member
213 * Runtime type information about a type.
214 * Can be retrieved for any type using a
215 * <a href="../expression.html#typeidexpression">TypeidExpression</a>.
219 override hash_t toHash()
222 foreach (char c; this.toString())
227 override int opCmp(Object o)
231 TypeInfo ti = cast(TypeInfo)o;
234 return dstrcmp(this.toString(), ti.toString());
237 override equals_t opEquals(Object o)
239 /* TypeInfo instances are singletons, but duplicates can exist
240 * across DLL's. Therefore, comparing for a name match is
245 TypeInfo ti = cast(TypeInfo)o;
246 return ti && this.toString() == ti.toString();
249 /// Returns a hash of the instance of a type.
250 hash_t getHash(in void* p) { return cast(hash_t)p; }
252 /// Compares two instances for equality.
253 equals_t equals(in void* p1, in void* p2) { return p1 == p2; }
255 /// Compares two instances for <, ==, or >.
256 int compare(in void* p1, in void* p2) { return 0; }
258 /// Returns size of the type.
259 size_t tsize() { return 0; }
261 /// Swaps two instances of the type.
262 void swap(void* p1, void* p2)
265 for (size_t i = 0; i < n; i++)
267 byte t = (cast(byte *)p1)[i];
268 (cast(byte*)p1)[i] = (cast(byte*)p2)[i];
269 (cast(byte*)p2)[i] = t;
273 /// Get TypeInfo for 'next' type, as defined by what kind of type this is,
275 TypeInfo next() { return null; }
277 /// Return default initializer, null if default initialize to 0
278 void[] init() { return null; }
280 /// Get flags for type: 1 means GC should scan for pointers
281 uint flags() { return 0; }
283 /// Get type information on the contents of the type; null if not available
284 OffsetTypeInfo[] offTi() { return null; }
287 class TypeInfo_Typedef : TypeInfo
289 override string toString() { return name; }
291 override equals_t opEquals(Object o)
295 ((c = cast(TypeInfo_Typedef)o) !is null &&
296 this.name == c.name &&
297 this.base == c.base);
300 override hash_t getHash(in void* p) { return base.getHash(p); }
301 override equals_t equals(in void* p1, in void* p2) { return base.equals(p1, p2); }
302 override int compare(in void* p1, in void* p2) { return base.compare(p1, p2); }
303 override size_t tsize() { return base.tsize(); }
304 override void swap(void* p1, void* p2) { return base.swap(p1, p2); }
306 override TypeInfo next() { return base.next(); }
307 override uint flags() { return base.flags(); }
308 override void[] init() { return m_init.length ? m_init : base.init(); }
315 class TypeInfo_Enum : TypeInfo_Typedef
320 class TypeInfo_Pointer : TypeInfo
322 override string toString() { return m_next.toString() ~ "*"; }
324 override equals_t opEquals(Object o)
328 ((c = cast(TypeInfo_Pointer)o) !is null &&
329 this.m_next == c.m_next);
332 override hash_t getHash(in void* p)
334 return cast(hash_t)*cast(void**)p;
337 override equals_t equals(in void* p1, in void* p2)
339 return *cast(void**)p1 == *cast(void**)p2;
342 override int compare(in void* p1, in void* p2)
344 if (*cast(void**)p1 < *cast(void**)p2)
346 else if (*cast(void**)p1 > *cast(void**)p2)
352 override size_t tsize()
354 return (void*).sizeof;
357 override void swap(void* p1, void* p2)
359 void* tmp = *cast(void**)p1;
360 *cast(void**)p1 = *cast(void**)p2;
361 *cast(void**)p2 = tmp;
364 override TypeInfo next() { return m_next; }
365 override uint flags() { return 1; }
370 class TypeInfo_Array : TypeInfo
372 override string toString() { return value.toString() ~ "[]"; }
374 override equals_t opEquals(Object o)
378 ((c = cast(TypeInfo_Array)o) !is null &&
379 this.value == c.value);
382 override hash_t getHash(in void* p)
384 size_t sz = value.tsize();
386 void[] a = *cast(void[]*)p;
387 for (size_t i = 0; i < a.length; i++)
388 hash += value.getHash(a.ptr + i * sz);
392 override equals_t equals(in void* p1, in void* p2)
394 void[] a1 = *cast(void[]*)p1;
395 void[] a2 = *cast(void[]*)p2;
396 if (a1.length != a2.length)
398 size_t sz = value.tsize();
399 for (size_t i = 0; i < a1.length; i++)
401 if (!value.equals(a1.ptr + i * sz, a2.ptr + i * sz))
407 override int compare(in void* p1, in void* p2)
409 void[] a1 = *cast(void[]*)p1;
410 void[] a2 = *cast(void[]*)p2;
411 size_t sz = value.tsize();
412 size_t len = a1.length;
416 for (size_t u = 0; u < len; u++)
418 int result = value.compare(a1.ptr + u * sz, a2.ptr + u * sz);
422 return cast(int)a1.length - cast(int)a2.length;
425 override size_t tsize()
427 return (void[]).sizeof;
430 override void swap(void* p1, void* p2)
432 void[] tmp = *cast(void[]*)p1;
433 *cast(void[]*)p1 = *cast(void[]*)p2;
434 *cast(void[]*)p2 = tmp;
439 override TypeInfo next()
444 override uint flags() { return 1; }
447 class TypeInfo_StaticArray : TypeInfo
449 override string toString()
452 return cast(string)(value.toString() ~ "[" ~ tmp.intToString(len) ~ "]");
455 override equals_t opEquals(Object o)
457 TypeInfo_StaticArray c;
459 ((c = cast(TypeInfo_StaticArray)o) !is null &&
461 this.value == c.value);
464 override hash_t getHash(in void* p)
466 size_t sz = value.tsize();
468 for (size_t i = 0; i < len; i++)
469 hash += value.getHash(p + i * sz);
473 override equals_t equals(in void* p1, in void* p2)
475 size_t sz = value.tsize();
477 for (size_t u = 0; u < len; u++)
479 if (!value.equals(p1 + u * sz, p2 + u * sz))
485 override int compare(in void* p1, in void* p2)
487 size_t sz = value.tsize();
489 for (size_t u = 0; u < len; u++)
491 int result = value.compare(p1 + u * sz, p2 + u * sz);
498 override size_t tsize()
500 return len * value.tsize();
503 override void swap(void* p1, void* p2)
506 size_t sz = value.tsize();
510 if (sz < buffer.sizeof)
513 tmp = pbuffer = (new void[sz]).ptr;
515 for (size_t u = 0; u < len; u += sz)
517 memcpy(tmp, p1 + o, sz);
518 memcpy(p1 + o, p2 + o, sz);
519 memcpy(p2 + o, tmp, sz);
525 override void[] init() { return value.init(); }
526 override TypeInfo next() { return value; }
527 override uint flags() { return value.flags(); }
533 class TypeInfo_AssociativeArray : TypeInfo
535 override string toString()
537 return cast(string)(next.toString() ~ "[" ~ key.toString() ~ "]");
540 override equals_t opEquals(Object o)
542 TypeInfo_AssociativeArray c;
544 ((c = cast(TypeInfo_AssociativeArray)o) !is null &&
546 this.value == c.value);
549 // BUG: need to add the rest of the functions
551 override size_t tsize()
553 return (char[int]).sizeof;
556 override TypeInfo next() { return value; }
557 override uint flags() { return 1; }
563 class TypeInfo_Function : TypeInfo
565 override string toString()
567 return cast(string)(next.toString() ~ "()");
570 override equals_t opEquals(Object o)
574 ((c = cast(TypeInfo_Function)o) !is null &&
575 this.next == c.next);
578 // BUG: need to add the rest of the functions
580 override size_t tsize()
582 return 0; // no size for functions
588 class TypeInfo_Delegate : TypeInfo
590 override string toString()
592 return cast(string)(next.toString() ~ " delegate()");
595 override equals_t opEquals(Object o)
599 ((c = cast(TypeInfo_Delegate)o) !is null &&
600 this.next == c.next);
603 // BUG: need to add the rest of the functions
605 override size_t tsize()
607 alias int delegate() dg;
611 override uint flags() { return 1; }
616 class TypeInfo_Class : TypeInfo
618 override string toString() { return info.name; }
620 override equals_t opEquals(Object o)
624 ((c = cast(TypeInfo_Class)o) !is null &&
625 this.info.name == c.classinfo.name);
628 override hash_t getHash(in void* p)
630 Object o = *cast(Object*)p;
631 return o ? o.toHash() : 0;
634 override equals_t equals(in void* p1, in void* p2)
636 Object o1 = *cast(Object*)p1;
637 Object o2 = *cast(Object*)p2;
639 return (o1 is o2) || (o1 && o1.opEquals(o2));
642 override int compare(in void* p1, in void* p2)
644 Object o1 = *cast(Object*)p1;
645 Object o2 = *cast(Object*)p2;
648 // Regard null references as always being "less than"
664 override size_t tsize()
666 return Object.sizeof;
669 override uint flags() { return 1; }
671 override OffsetTypeInfo[] offTi()
673 return (info.flags & 4) ? info.offTi : null;
679 class TypeInfo_Interface : TypeInfo
681 override string toString() { return info.name; }
683 override equals_t opEquals(Object o)
685 TypeInfo_Interface c;
687 ((c = cast(TypeInfo_Interface)o) !is null &&
688 this.info.name == c.classinfo.name);
691 override hash_t getHash(in void* p)
693 Interface* pi = **cast(Interface ***)*cast(void**)p;
694 Object o = cast(Object)(*cast(void**)p - pi.offset);
699 override equals_t equals(in void* p1, in void* p2)
701 Interface* pi = **cast(Interface ***)*cast(void**)p1;
702 Object o1 = cast(Object)(*cast(void**)p1 - pi.offset);
703 pi = **cast(Interface ***)*cast(void**)p2;
704 Object o2 = cast(Object)(*cast(void**)p2 - pi.offset);
706 return o1 == o2 || (o1 && o1.opCmp(o2) == 0);
709 override int compare(in void* p1, in void* p2)
711 Interface* pi = **cast(Interface ***)*cast(void**)p1;
712 Object o1 = cast(Object)(*cast(void**)p1 - pi.offset);
713 pi = **cast(Interface ***)*cast(void**)p2;
714 Object o2 = cast(Object)(*cast(void**)p2 - pi.offset);
717 // Regard null references as always being "less than"
733 override size_t tsize()
735 return Object.sizeof;
738 override uint flags() { return 1; }
743 class TypeInfo_Struct : TypeInfo
745 override string toString() { return name; }
747 override equals_t opEquals(Object o)
751 ((s = cast(TypeInfo_Struct)o) !is null &&
752 this.name == s.name &&
753 this.init.length == s.init.length);
756 override hash_t getHash(in void* p)
761 debug(PRINTF) printf("getHash() using xtoHash\n");
762 return (*xtoHash)(p);
767 debug(PRINTF) printf("getHash() using default hash\n");
768 // A sorry hash algorithm.
769 // Should use the one for strings.
770 // BUG: relies on the GC not moving objects
771 auto q = cast(ubyte*)p;
772 for (size_t i = 0; i < init.length; i++)
781 override equals_t equals(in void* p1, in void* p2)
788 return (*xopEquals)(p1, p2);
790 // BUG: relies on the GC not moving objects
791 return memcmp(p1, p2, init.length) == 0;
794 override int compare(in void* p1, in void* p2)
796 // Regard null references as always being "less than"
804 return (*xopCmp)(p2, p1);
806 // BUG: relies on the GC not moving objects
807 return memcmp(p1, p2, init.length);
815 override size_t tsize()
820 override void[] init() { return m_init; }
822 override uint flags() { return m_flags; }
825 void[] m_init; // initializer; init.ptr == null if 0 initialize
827 hash_t function(in void*) xtoHash;
828 equals_t function(in void*, in void*) xopEquals;
829 int function(in void*, in void*) xopCmp;
830 char[] function(in void*) xtoString;
835 class TypeInfo_Tuple : TypeInfo
839 override string toString()
842 foreach (i, element; elements)
846 s ~= element.toString();
852 override equals_t opEquals(Object o)
857 auto t = cast(TypeInfo_Tuple)o;
858 if (t && elements.length == t.elements.length)
860 for (size_t i = 0; i < elements.length; i++)
862 if (elements[i] != t.elements[i])
870 override hash_t getHash(in void* p)
875 override equals_t equals(in void* p1, in void* p2)
880 override int compare(in void* p1, in void* p2)
885 override size_t tsize()
890 override void swap(void* p1, void* p2)
897 ///////////////////////////////////////////////////////////////////////////////
899 ///////////////////////////////////////////////////////////////////////////////
902 class Exception : Object
906 int opApply( int delegate(inout char[]) );
915 this( string msg, Exception next = null )
919 this.info = traceContext();
922 this( string msg, string file, size_t line, Exception next = null )
927 this.info = traceContext();
930 override string toString()
937 alias Exception.TraceInfo function( void* ptr = null ) TraceHandler;
938 private TraceHandler traceHandler = null;
942 * Overrides the default trace hander with a user-supplied version.
945 * h = The new trace handler. Set to null to use the default handler.
947 extern (C) void rt_setTraceHandler( TraceHandler h )
954 * This function will be called when an Exception is constructed. The
955 * user-supplied trace handler will be called if one has been supplied,
956 * otherwise no trace will be generated.
959 * ptr = A pointer to the location from which to generate the trace, or null
960 * if the trace should be generated from within the trace handler
964 * An object describing the current calling context or null if no handler is
967 Exception.TraceInfo traceContext( void* ptr = null )
969 if( traceHandler is null )
971 return traceHandler( ptr );
975 ///////////////////////////////////////////////////////////////////////////////
977 ///////////////////////////////////////////////////////////////////////////////
982 MIctorstart = 1, // we've started constructing it
983 MIctordone = 2, // finished construction
984 MIstandalone = 4, // module ctor does not depend on other module
985 // ctors being done first
986 MIhasictor = 8, // has ictor member
993 ModuleInfo[] importedModules;
994 ClassInfo[] localClasses;
997 void function() ctor; // module static constructor (order dependent)
998 void function() dtor; // module static destructor
999 void function() unitTest; // module unit tests
1001 void* xgetMembers; // module getMembers() function
1003 void function() ictor; // module static constructor (order independent)
1005 static int opApply( int delegate(inout ModuleInfo) dg )
1009 foreach( m; _moduleinfo_array )
1020 // Windows: this gets initialized by minit.asm
1021 // linux: this gets initialized in _moduleCtor()
1022 extern (C) ModuleInfo[] _moduleinfo_array;
1027 // This linked list is created by a compiler generated function inserted
1028 // into the .ctor list by the compiler.
1029 struct ModuleReference
1031 ModuleReference* next;
1035 extern (C) ModuleReference* _Dmodule_ref; // start of linked list
1038 ModuleInfo[] _moduleinfo_dtors;
1039 uint _moduleinfo_dtors_i;
1041 // Register termination function pointers
1042 extern (C) int _fatexit(void*);
1045 * Initialize the modules.
1048 extern (C) void _moduleCtor()
1050 debug(PRINTF) printf("_moduleCtor()\n");
1054 ModuleReference *mr;
1056 for (mr = _Dmodule_ref; mr; mr = mr.next)
1058 _moduleinfo_array = new ModuleInfo[len];
1060 for (mr = _Dmodule_ref; mr; mr = mr.next)
1061 { _moduleinfo_array[len] = mr.mod;
1068 // Ensure module destructors also get called on program termination
1069 //_fatexit(&_STD_moduleDtor);
1072 _moduleinfo_dtors = new ModuleInfo[_moduleinfo_array.length];
1073 debug(PRINTF) printf("_moduleinfo_dtors = x%x\n", cast(void*)_moduleinfo_dtors);
1074 _moduleIndependentCtors();
1075 _moduleCtor2(_moduleinfo_array, 0);
1078 extern (C) void _moduleIndependentCtors()
1080 debug(PRINTF) printf("_moduleIndependentCtors()\n");
1081 foreach (m; _moduleinfo_array)
1083 if (m && m.flags & MIhasictor && m.ictor)
1090 void _moduleCtor2(ModuleInfo[] mi, int skip)
1092 debug(PRINTF) printf("_moduleCtor2(): %d modules\n", mi.length);
1093 for (uint i = 0; i < mi.length; i++)
1095 ModuleInfo m = mi[i];
1097 debug(PRINTF) printf("\tmodule[%d] = '%p'\n", i, m);
1100 debug(PRINTF) printf("\tmodule[%d] = '%.*s'\n", i, m.name);
1101 if (m.flags & MIctordone)
1103 debug(PRINTF) printf("\tmodule[%d] = '%.*s', m = x%x\n", i, m.name, m);
1105 if (m.ctor || m.dtor)
1107 if (m.flags & MIctorstart)
1108 { if (skip || m.flags & MIstandalone)
1110 throw new Exception( "Cyclic dependency in module " ~ m.name );
1113 m.flags |= MIctorstart;
1114 _moduleCtor2(m.importedModules, 0);
1117 m.flags &= ~MIctorstart;
1118 m.flags |= MIctordone;
1120 // Now that construction is done, register the destructor
1121 //printf("\tadding module dtor x%x\n", m);
1122 assert(_moduleinfo_dtors_i < _moduleinfo_dtors.length);
1123 _moduleinfo_dtors[_moduleinfo_dtors_i++] = m;
1127 m.flags |= MIctordone;
1128 _moduleCtor2(m.importedModules, 1);
1134 * Destruct the modules.
1137 // Starting the name with "_STD" means under linux a pointer to the
1138 // function gets put in the .dtors segment.
1140 extern (C) void _moduleDtor()
1142 debug(PRINTF) printf("_moduleDtor(): %d modules\n", _moduleinfo_dtors_i);
1144 for (uint i = _moduleinfo_dtors_i; i-- != 0;)
1146 ModuleInfo m = _moduleinfo_dtors[i];
1148 debug(PRINTF) printf("\tmodule[%d] = '%.*s', x%x\n", i, m.name, m);
1154 debug(PRINTF) printf("_moduleDtor() done\n");
1157 ///////////////////////////////////////////////////////////////////////////////
1159 ///////////////////////////////////////////////////////////////////////////////
1161 alias Object.Monitor IMonitor;
1162 alias void delegate(Object) DEvent;
1164 // NOTE: The dtor callback feature is only supported for monitors that are not
1165 // supplied by the user. The assumption is that any object with a user-
1166 // supplied monitor may have special storage or lifetime requirements and
1167 // that as a result, storing references to local objects within Monitor
1168 // may not be safe or desirable. Thus, devt is only valid if impl is
1178 Monitor* getMonitor(Object h)
1180 return cast(Monitor*) (cast(void**) h)[1];
1183 void setMonitor(Object h, Monitor* m)
1185 (cast(void**) h)[1] = m;
1188 extern (C) void _d_monitor_create(Object);
1189 extern (C) void _d_monitor_destroy(Object);
1190 extern (C) void _d_monitor_lock(Object);
1191 extern (C) int _d_monitor_unlock(Object);
1193 extern (C) void _d_monitordelete(Object h, bool det)
1195 Monitor* m = getMonitor(h);
1199 IMonitor i = m.impl;
1202 _d_monitor_devt(m, h);
1203 _d_monitor_destroy(h);
1204 setMonitor(h, null);
1207 if (det && (cast(void*) i) !is (cast(void*) h))
1209 setMonitor(h, null);
1213 extern (C) void _d_monitorenter(Object h)
1215 Monitor* m = getMonitor(h);
1219 _d_monitor_create(h);
1223 IMonitor i = m.impl;
1233 extern (C) void _d_monitorexit(Object h)
1235 Monitor* m = getMonitor(h);
1236 IMonitor i = m.impl;
1240 _d_monitor_unlock(h);
1246 extern (C) void _d_monitor_devt(Monitor* m, Object h)
1266 extern (C) void rt_attachDisposeEvent(Object h, DEvent e)
1270 Monitor* m = getMonitor(h);
1271 assert(m.impl is null);
1273 foreach (inout v; m.devt)
1275 if (v is null || v == e)
1282 auto len = m.devt.length + 4; // grow by 4 elements
1283 auto pos = m.devt.length; // insert position
1284 auto p = realloc(m.devt.ptr, DEvent.sizeof * len);
1286 onOutOfMemoryError();
1287 m.devt = (cast(DEvent*)p)[0 .. len];
1288 m.devt[pos+1 .. len] = null;
1293 extern (C) void rt_detachDisposeEvent(Object h, DEvent e)
1297 Monitor* m = getMonitor(h);
1298 assert(m.impl is null);
1300 foreach (p, v; m.devt)
1306 (m.devt.length - p - 1) * DEvent.sizeof);
1307 m.devt[$ - 1] = null;