Mercurial > projects > ldc
comparison tango/lib/compiler/llvmdc/genobj.d @ 132:1700239cab2e trunk
[svn r136] MAJOR UNSTABLE UPDATE!!!
Initial commit after moving to Tango instead of Phobos.
Lots of bugfixes...
This build is not suitable for most things.
author | lindquist |
---|---|
date | Fri, 11 Jan 2008 17:57:40 +0100 |
parents | |
children | 44a95ac7368a |
comparison
equal
deleted
inserted
replaced
131:5825d48b27d1 | 132:1700239cab2e |
---|---|
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 <sean@f4.ca> for use with Tango. | |
36 */ | |
37 | |
38 module object; | |
39 | |
40 private | |
41 { | |
42 import tango.stdc.string; // : memcmp, memcpy; | |
43 import tango.stdc.stdlib; // : calloc, realloc, free; | |
44 import util.string; | |
45 debug(PRINTF) import tango.stdc.stdio; // : printf; | |
46 | |
47 extern (C) void onOutOfMemoryError(); | |
48 extern (C) Object _d_newclass(ClassInfo ci); | |
49 } | |
50 | |
51 // NOTE: For some reason, this declaration method doesn't work | |
52 // in this particular file (and this file only). It must | |
53 // be a DMD thing. | |
54 //alias typeof(int.sizeof) size_t; | |
55 //alias typeof(cast(void*)0 - cast(void*)0) ptrdiff_t; | |
56 | |
57 version( X86_64 ) | |
58 { | |
59 alias ulong size_t; | |
60 alias long ptrdiff_t; | |
61 } | |
62 else | |
63 { | |
64 alias uint size_t; | |
65 alias int ptrdiff_t; | |
66 } | |
67 | |
68 alias size_t hash_t; | |
69 | |
70 /** | |
71 * All D class objects inherit from Object. | |
72 */ | |
73 class Object | |
74 { | |
75 /** | |
76 * Convert Object to a human readable string. | |
77 */ | |
78 char[] toString() | |
79 { | |
80 return this.classinfo.name; | |
81 } | |
82 | |
83 /** | |
84 * Compute hash function for Object. | |
85 */ | |
86 hash_t toHash() | |
87 { | |
88 // BUG: this prevents a compacting GC from working, needs to be fixed | |
89 return cast(hash_t)cast(void*)this; | |
90 } | |
91 | |
92 /** | |
93 * Compare with another Object obj. | |
94 * Returns: | |
95 * $(TABLE | |
96 * $(TR $(TD this < obj) $(TD < 0)) | |
97 * $(TR $(TD this == obj) $(TD 0)) | |
98 * $(TR $(TD this > obj) $(TD > 0)) | |
99 * ) | |
100 */ | |
101 int opCmp(Object o) | |
102 { | |
103 // BUG: this prevents a compacting GC from working, needs to be fixed | |
104 //return cast(int)cast(void*)this - cast(int)cast(void*)o; | |
105 | |
106 //throw new Exception("need opCmp for class " ~ this.classinfo.name); | |
107 return this !is o; | |
108 } | |
109 | |
110 /** | |
111 * Returns !=0 if this object does have the same contents as obj. | |
112 */ | |
113 int opEquals(Object o) | |
114 { | |
115 return cast(int)(this is o); | |
116 } | |
117 | |
118 interface Monitor | |
119 { | |
120 void lock(); | |
121 void unlock(); | |
122 } | |
123 } | |
124 | |
125 /** | |
126 * Information about an interface. | |
127 * A pointer to this appears as the first entry in the interface's vtbl[]. | |
128 */ | |
129 struct Interface | |
130 { | |
131 ClassInfo classinfo; /// .classinfo for this interface (not for containing class) | |
132 void*[] vtbl; | |
133 ptrdiff_t offset; /// offset to Interface 'this' from Object 'this' | |
134 } | |
135 | |
136 /** | |
137 * Runtime type information about a class. Can be retrieved for any class type | |
138 * or instance by using the .classinfo property. | |
139 * A pointer to this appears as the first entry in the class's vtbl[]. | |
140 */ | |
141 class ClassInfo : Object | |
142 { | |
143 byte[] init; /** class static initializer | |
144 * (init.length gives size in bytes of class) | |
145 */ | |
146 char[] name; /// class name | |
147 void*[] vtbl; /// virtual function pointer table | |
148 Interface[] interfaces; /// interfaces this class implements | |
149 ClassInfo base; /// base class | |
150 void* destructor; | |
151 void function(Object) classInvariant; | |
152 uint flags; | |
153 // 1: // IUnknown | |
154 // 2: // has no possible pointers into GC memory | |
155 // 4: // has offTi[] member | |
156 // 8: // has constructors | |
157 void* deallocator; | |
158 OffsetTypeInfo[] offTi; | |
159 void function(Object) defaultConstructor; // default Constructor | |
160 | |
161 /** | |
162 * Search all modules for ClassInfo corresponding to classname. | |
163 * Returns: null if not found | |
164 */ | |
165 static ClassInfo find(char[] classname) | |
166 { | |
167 foreach (m; ModuleInfo) | |
168 { | |
169 //writefln("module %s, %d", m.name, m.localClasses.length); | |
170 foreach (c; m.localClasses) | |
171 { | |
172 //writefln("\tclass %s", c.name); | |
173 if (c.name == classname) | |
174 return c; | |
175 } | |
176 } | |
177 return null; | |
178 } | |
179 | |
180 /** | |
181 * Create instance of Object represented by 'this'. | |
182 */ | |
183 Object create() | |
184 { | |
185 if (flags & 8 && !defaultConstructor) | |
186 return null; | |
187 Object o = _d_newclass(this); | |
188 if (flags & 8 && defaultConstructor) | |
189 { | |
190 defaultConstructor(o); | |
191 } | |
192 return o; | |
193 } | |
194 } | |
195 | |
196 /** | |
197 * Array of pairs giving the offset and type information for each | |
198 * member in an aggregate. | |
199 */ | |
200 struct OffsetTypeInfo | |
201 { | |
202 size_t offset; /// Offset of member from start of object | |
203 TypeInfo ti; /// TypeInfo for this member | |
204 } | |
205 | |
206 /** | |
207 * Runtime type information about a type. | |
208 * Can be retrieved for any type using a | |
209 * <a href="../expression.html#typeidexpression">TypeidExpression</a>. | |
210 */ | |
211 class TypeInfo | |
212 { | |
213 hash_t toHash() | |
214 { hash_t hash; | |
215 | |
216 foreach (char c; this.toString()) | |
217 hash = hash * 9 + c; | |
218 return hash; | |
219 } | |
220 | |
221 int opCmp(Object o) | |
222 { | |
223 if (this is o) | |
224 return 0; | |
225 TypeInfo ti = cast(TypeInfo)o; | |
226 if (ti is null) | |
227 return 1; | |
228 return stringCompare(this.toString(), ti.toString()); | |
229 } | |
230 | |
231 int opEquals(Object o) | |
232 { | |
233 /* TypeInfo instances are singletons, but duplicates can exist | |
234 * across DLL's. Therefore, comparing for a name match is | |
235 * sufficient. | |
236 */ | |
237 if (this is o) | |
238 return 1; | |
239 TypeInfo ti = cast(TypeInfo)o; | |
240 return cast(int)(ti && this.toString() == ti.toString()); | |
241 } | |
242 | |
243 /// Returns a hash of the instance of a type. | |
244 hash_t getHash(void *p) { return cast(hash_t)p; } | |
245 | |
246 /// Compares two instances for equality. | |
247 int equals(void *p1, void *p2) { return cast(int)(p1 == p2); } | |
248 | |
249 /// Compares two instances for <, ==, or >. | |
250 int compare(void *p1, void *p2) { return 0; } | |
251 | |
252 /// Returns size of the type. | |
253 size_t tsize() { return 0; } | |
254 | |
255 /// Swaps two instances of the type. | |
256 void swap(void *p1, void *p2) | |
257 { | |
258 size_t n = tsize(); | |
259 for (size_t i = 0; i < n; i++) | |
260 { byte t; | |
261 | |
262 t = (cast(byte *)p1)[i]; | |
263 (cast(byte *)p1)[i] = (cast(byte *)p2)[i]; | |
264 (cast(byte *)p2)[i] = t; | |
265 } | |
266 } | |
267 | |
268 /// Get TypeInfo for 'next' type, as defined by what kind of type this is, | |
269 /// null if none. | |
270 TypeInfo next() { return null; } | |
271 | |
272 /// Return default initializer, null if default initialize to 0 | |
273 void[] init() { return null; } | |
274 | |
275 /// Get flags for type: 1 means GC should scan for pointers | |
276 uint flags() { return 0; } | |
277 | |
278 /// Get type information on the contents of the type; null if not available | |
279 OffsetTypeInfo[] offTi() { return null; } | |
280 } | |
281 | |
282 class TypeInfo_Typedef : TypeInfo | |
283 { | |
284 char[] toString() { return name; } | |
285 | |
286 int opEquals(Object o) | |
287 { TypeInfo_Typedef c; | |
288 | |
289 return cast(int) | |
290 (this is o || | |
291 ((c = cast(TypeInfo_Typedef)o) !is null && | |
292 this.name == c.name && | |
293 this.base == c.base)); | |
294 } | |
295 | |
296 hash_t getHash(void *p) { return base.getHash(p); } | |
297 int equals(void *p1, void *p2) { return base.equals(p1, p2); } | |
298 int compare(void *p1, void *p2) { return base.compare(p1, p2); } | |
299 size_t tsize() { return base.tsize(); } | |
300 void swap(void *p1, void *p2) { return base.swap(p1, p2); } | |
301 | |
302 TypeInfo next() { return base.next(); } | |
303 uint flags() { return base.flags(); } | |
304 void[] init() { return m_init.length ? m_init : base.init(); } | |
305 | |
306 TypeInfo base; | |
307 char[] name; | |
308 void[] m_init; | |
309 } | |
310 | |
311 class TypeInfo_Enum : TypeInfo_Typedef | |
312 { | |
313 } | |
314 | |
315 class TypeInfo_Pointer : TypeInfo | |
316 { | |
317 char[] toString() { return m_next.toString() ~ "*"; } | |
318 | |
319 int opEquals(Object o) | |
320 { TypeInfo_Pointer c; | |
321 | |
322 return this is o || | |
323 ((c = cast(TypeInfo_Pointer)o) !is null && | |
324 this.m_next == c.m_next); | |
325 } | |
326 | |
327 hash_t getHash(void *p) | |
328 { | |
329 return cast(hash_t)*cast(void**)p; | |
330 } | |
331 | |
332 int equals(void *p1, void *p2) | |
333 { | |
334 return cast(int)(*cast(void* *)p1 == *cast(void* *)p2); | |
335 } | |
336 | |
337 int compare(void *p1, void *p2) | |
338 { | |
339 if (*cast(void* *)p1 < *cast(void* *)p2) | |
340 return -1; | |
341 else if (*cast(void* *)p1 > *cast(void* *)p2) | |
342 return 1; | |
343 else | |
344 return 0; | |
345 } | |
346 | |
347 size_t tsize() | |
348 { | |
349 return (void*).sizeof; | |
350 } | |
351 | |
352 void swap(void *p1, void *p2) | |
353 { void* tmp; | |
354 tmp = *cast(void**)p1; | |
355 *cast(void**)p1 = *cast(void**)p2; | |
356 *cast(void**)p2 = tmp; | |
357 } | |
358 | |
359 TypeInfo next() { return m_next; } | |
360 uint flags() { return 1; } | |
361 | |
362 TypeInfo m_next; | |
363 } | |
364 | |
365 class TypeInfo_Array : TypeInfo | |
366 { | |
367 char[] toString() { return value.toString() ~ "[]"; } | |
368 | |
369 int opEquals(Object o) | |
370 { TypeInfo_Array c; | |
371 | |
372 return cast(int) | |
373 (this is o || | |
374 ((c = cast(TypeInfo_Array)o) !is null && | |
375 this.value == c.value)); | |
376 } | |
377 | |
378 hash_t getHash(void *p) | |
379 { size_t sz = value.tsize(); | |
380 hash_t hash = 0; | |
381 void[] a = *cast(void[]*)p; | |
382 for (size_t i = 0; i < a.length; i++) | |
383 hash += value.getHash(a.ptr + i * sz); | |
384 return hash; | |
385 } | |
386 | |
387 int equals(void *p1, void *p2) | |
388 { | |
389 void[] a1 = *cast(void[]*)p1; | |
390 void[] a2 = *cast(void[]*)p2; | |
391 if (a1.length != a2.length) | |
392 return 0; | |
393 size_t sz = value.tsize(); | |
394 for (size_t i = 0; i < a1.length; i++) | |
395 { | |
396 if (!value.equals(a1.ptr + i * sz, a2.ptr + i * sz)) | |
397 return 0; | |
398 } | |
399 return 1; | |
400 } | |
401 | |
402 int compare(void *p1, void *p2) | |
403 { | |
404 void[] a1 = *cast(void[]*)p1; | |
405 void[] a2 = *cast(void[]*)p2; | |
406 size_t sz = value.tsize(); | |
407 size_t len = a1.length; | |
408 | |
409 if (a2.length < len) | |
410 len = a2.length; | |
411 for (size_t u = 0; u < len; u++) | |
412 { | |
413 int result = value.compare(a1.ptr + u * sz, a2.ptr + u * sz); | |
414 if (result) | |
415 return result; | |
416 } | |
417 return cast(int)a1.length - cast(int)a2.length; | |
418 } | |
419 | |
420 size_t tsize() | |
421 { | |
422 return (void[]).sizeof; | |
423 } | |
424 | |
425 void swap(void *p1, void *p2) | |
426 { void[] tmp; | |
427 tmp = *cast(void[]*)p1; | |
428 *cast(void[]*)p1 = *cast(void[]*)p2; | |
429 *cast(void[]*)p2 = tmp; | |
430 } | |
431 | |
432 TypeInfo value; | |
433 | |
434 TypeInfo next() | |
435 { | |
436 return value; | |
437 } | |
438 | |
439 uint flags() { return 1; } | |
440 } | |
441 | |
442 class TypeInfo_StaticArray : TypeInfo | |
443 { | |
444 char[] toString() | |
445 { | |
446 char [10] tmp = void; | |
447 return value.toString() ~ "[" ~ intToUtf8(tmp, len) ~ "]"; | |
448 } | |
449 | |
450 int opEquals(Object o) | |
451 { TypeInfo_StaticArray c; | |
452 | |
453 return cast(int) | |
454 (this is o || | |
455 ((c = cast(TypeInfo_StaticArray)o) !is null && | |
456 this.len == c.len && | |
457 this.value == c.value)); | |
458 } | |
459 | |
460 hash_t getHash(void *p) | |
461 { size_t sz = value.tsize(); | |
462 hash_t hash = 0; | |
463 for (size_t i = 0; i < len; i++) | |
464 hash += value.getHash(p + i * sz); | |
465 return hash; | |
466 } | |
467 | |
468 int equals(void *p1, void *p2) | |
469 { | |
470 size_t sz = value.tsize(); | |
471 | |
472 for (size_t u = 0; u < len; u++) | |
473 { | |
474 if (!value.equals(p1 + u * sz, p2 + u * sz)) | |
475 return 0; | |
476 } | |
477 return 1; | |
478 } | |
479 | |
480 int compare(void *p1, void *p2) | |
481 { | |
482 size_t sz = value.tsize(); | |
483 | |
484 for (size_t u = 0; u < len; u++) | |
485 { | |
486 int result = value.compare(p1 + u * sz, p2 + u * sz); | |
487 if (result) | |
488 return result; | |
489 } | |
490 return 0; | |
491 } | |
492 | |
493 size_t tsize() | |
494 { | |
495 return len * value.tsize(); | |
496 } | |
497 | |
498 void swap(void *p1, void *p2) | |
499 { void* tmp; | |
500 size_t sz = value.tsize(); | |
501 ubyte[16] buffer; | |
502 void* pbuffer; | |
503 | |
504 if (sz < buffer.sizeof) | |
505 tmp = buffer.ptr; | |
506 else | |
507 tmp = pbuffer = (new void[sz]).ptr; | |
508 | |
509 for (size_t u = 0; u < len; u += sz) | |
510 { size_t o = u * sz; | |
511 memcpy(tmp, p1 + o, sz); | |
512 memcpy(p1 + o, p2 + o, sz); | |
513 memcpy(p2 + o, tmp, sz); | |
514 } | |
515 if (pbuffer) | |
516 delete pbuffer; | |
517 } | |
518 | |
519 void[] init() { return value.init(); } | |
520 TypeInfo next() { return value; } | |
521 uint flags() { return value.flags(); } | |
522 | |
523 TypeInfo value; | |
524 size_t len; | |
525 } | |
526 | |
527 class TypeInfo_AssociativeArray : TypeInfo | |
528 { | |
529 char[] toString() | |
530 { | |
531 return next.toString() ~ "[" ~ key.toString() ~ "]"; | |
532 } | |
533 | |
534 int opEquals(Object o) | |
535 { TypeInfo_AssociativeArray c; | |
536 | |
537 return this is o || | |
538 ((c = cast(TypeInfo_AssociativeArray)o) !is null && | |
539 this.key == c.key && | |
540 this.value == c.value); | |
541 } | |
542 | |
543 // BUG: need to add the rest of the functions | |
544 | |
545 size_t tsize() | |
546 { | |
547 return (char[int]).sizeof; | |
548 } | |
549 | |
550 TypeInfo next() { return value; } | |
551 uint flags() { return 1; } | |
552 | |
553 TypeInfo value; | |
554 TypeInfo key; | |
555 } | |
556 | |
557 class TypeInfo_Function : TypeInfo | |
558 { | |
559 char[] toString() | |
560 { | |
561 return next.toString() ~ "()"; | |
562 } | |
563 | |
564 int opEquals(Object o) | |
565 { TypeInfo_Function c; | |
566 | |
567 return this is o || | |
568 ((c = cast(TypeInfo_Function)o) !is null && | |
569 this.next == c.next); | |
570 } | |
571 | |
572 // BUG: need to add the rest of the functions | |
573 | |
574 size_t tsize() | |
575 { | |
576 return 0; // no size for functions | |
577 } | |
578 | |
579 TypeInfo next; | |
580 } | |
581 | |
582 class TypeInfo_Delegate : TypeInfo | |
583 { | |
584 char[] toString() | |
585 { | |
586 return next.toString() ~ " delegate()"; | |
587 } | |
588 | |
589 int opEquals(Object o) | |
590 { TypeInfo_Delegate c; | |
591 | |
592 return this is o || | |
593 ((c = cast(TypeInfo_Delegate)o) !is null && | |
594 this.next == c.next); | |
595 } | |
596 | |
597 // BUG: need to add the rest of the functions | |
598 | |
599 size_t tsize() | |
600 { alias int delegate() dg; | |
601 return dg.sizeof; | |
602 } | |
603 | |
604 uint flags() { return 1; } | |
605 | |
606 TypeInfo next; | |
607 } | |
608 | |
609 class TypeInfo_Class : TypeInfo | |
610 { | |
611 char[] toString() { return info.name; } | |
612 | |
613 int opEquals(Object o) | |
614 { TypeInfo_Class c; | |
615 | |
616 return this is o || | |
617 ((c = cast(TypeInfo_Class)o) !is null && | |
618 this.info.name == c.classinfo.name); | |
619 } | |
620 | |
621 hash_t getHash(void *p) | |
622 { | |
623 Object o = *cast(Object*)p; | |
624 assert(o); | |
625 return o.toHash(); | |
626 } | |
627 | |
628 int equals(void *p1, void *p2) | |
629 { | |
630 Object o1 = *cast(Object*)p1; | |
631 Object o2 = *cast(Object*)p2; | |
632 | |
633 return (o1 is o2) || (o1 && o1.opEquals(o2)); | |
634 } | |
635 | |
636 int compare(void *p1, void *p2) | |
637 { | |
638 Object o1 = *cast(Object*)p1; | |
639 Object o2 = *cast(Object*)p2; | |
640 int c = 0; | |
641 | |
642 // Regard null references as always being "less than" | |
643 if (o1 !is o2) | |
644 { | |
645 if (o1) | |
646 { if (!o2) | |
647 c = 1; | |
648 else | |
649 c = o1.opCmp(o2); | |
650 } | |
651 else | |
652 c = -1; | |
653 } | |
654 return c; | |
655 } | |
656 | |
657 size_t tsize() | |
658 { | |
659 return Object.sizeof; | |
660 } | |
661 | |
662 uint flags() { return 1; } | |
663 | |
664 OffsetTypeInfo[] offTi() | |
665 { | |
666 return (info.flags & 4) ? info.offTi : null; | |
667 } | |
668 | |
669 ClassInfo info; | |
670 } | |
671 | |
672 class TypeInfo_Interface : TypeInfo | |
673 { | |
674 char[] toString() { return info.name; } | |
675 | |
676 int opEquals(Object o) | |
677 { TypeInfo_Interface c; | |
678 | |
679 return this is o || | |
680 ((c = cast(TypeInfo_Interface)o) !is null && | |
681 this.info.name == c.classinfo.name); | |
682 } | |
683 | |
684 hash_t getHash(void *p) | |
685 { | |
686 Interface* pi = **cast(Interface ***)*cast(void**)p; | |
687 Object o = cast(Object)(*cast(void**)p - pi.offset); | |
688 assert(o); | |
689 return o.toHash(); | |
690 } | |
691 | |
692 int equals(void *p1, void *p2) | |
693 { | |
694 Interface* pi = **cast(Interface ***)*cast(void**)p1; | |
695 Object o1 = cast(Object)(*cast(void**)p1 - pi.offset); | |
696 pi = **cast(Interface ***)*cast(void**)p2; | |
697 Object o2 = cast(Object)(*cast(void**)p2 - pi.offset); | |
698 | |
699 return o1 == o2 || (o1 && o1.opCmp(o2) == 0); | |
700 } | |
701 | |
702 int compare(void *p1, void *p2) | |
703 { | |
704 Interface* pi = **cast(Interface ***)*cast(void**)p1; | |
705 Object o1 = cast(Object)(*cast(void**)p1 - pi.offset); | |
706 pi = **cast(Interface ***)*cast(void**)p2; | |
707 Object o2 = cast(Object)(*cast(void**)p2 - pi.offset); | |
708 int c = 0; | |
709 | |
710 // Regard null references as always being "less than" | |
711 if (o1 != o2) | |
712 { | |
713 if (o1) | |
714 { if (!o2) | |
715 c = 1; | |
716 else | |
717 c = o1.opCmp(o2); | |
718 } | |
719 else | |
720 c = -1; | |
721 } | |
722 return c; | |
723 } | |
724 | |
725 size_t tsize() | |
726 { | |
727 return Object.sizeof; | |
728 } | |
729 | |
730 uint flags() { return 1; } | |
731 | |
732 ClassInfo info; | |
733 } | |
734 | |
735 class TypeInfo_Struct : TypeInfo | |
736 { | |
737 char[] toString() { return name; } | |
738 | |
739 int opEquals(Object o) | |
740 { TypeInfo_Struct s; | |
741 | |
742 return this is o || | |
743 ((s = cast(TypeInfo_Struct)o) !is null && | |
744 this.name == s.name && | |
745 this.init.length == s.init.length); | |
746 } | |
747 | |
748 hash_t getHash(void *p) | |
749 { hash_t h; | |
750 | |
751 assert(p); | |
752 if (xtoHash) | |
753 { debug(PRINTF) printf("getHash() using xtoHash\n"); | |
754 h = (*xtoHash)(p); | |
755 } | |
756 else | |
757 { | |
758 debug(PRINTF) printf("getHash() using default hash\n"); | |
759 // A sorry hash algorithm. | |
760 // Should use the one for strings. | |
761 // BUG: relies on the GC not moving objects | |
762 for (size_t i = 0; i < init.length; i++) | |
763 { h = h * 9 + *cast(ubyte*)p; | |
764 p++; | |
765 } | |
766 } | |
767 return h; | |
768 } | |
769 | |
770 int equals(void *p2, void *p1) | |
771 { int c; | |
772 | |
773 if (p1 == p2) | |
774 c = 1; | |
775 else if (!p1 || !p2) | |
776 c = 0; | |
777 else if (xopEquals) | |
778 c = (*xopEquals)(p1, p2); | |
779 else | |
780 // BUG: relies on the GC not moving objects | |
781 c = (memcmp(p1, p2, init.length) == 0); | |
782 return c; | |
783 } | |
784 | |
785 int compare(void *p2, void *p1) | |
786 { | |
787 int c = 0; | |
788 | |
789 // Regard null references as always being "less than" | |
790 if (p1 != p2) | |
791 { | |
792 if (p1) | |
793 { if (!p2) | |
794 c = 1; | |
795 else if (xopCmp) | |
796 c = (*xopCmp)(p1, p2); | |
797 else | |
798 // BUG: relies on the GC not moving objects | |
799 c = memcmp(p1, p2, init.length); | |
800 } | |
801 else | |
802 c = -1; | |
803 } | |
804 return c; | |
805 } | |
806 | |
807 size_t tsize() | |
808 { | |
809 return init.length; | |
810 } | |
811 | |
812 void[] init() { return m_init; } | |
813 | |
814 uint flags() { return m_flags; } | |
815 | |
816 char[] name; | |
817 void[] m_init; // initializer; init.ptr == null if 0 initialize | |
818 | |
819 hash_t function(void*) xtoHash; | |
820 int function(void*,void*) xopEquals; | |
821 int function(void*,void*) xopCmp; | |
822 char[] function(void*) xtoString; | |
823 | |
824 uint m_flags; | |
825 } | |
826 | |
827 class TypeInfo_Tuple : TypeInfo | |
828 { | |
829 TypeInfo[] elements; | |
830 | |
831 char[] toString() | |
832 { | |
833 char[] s; | |
834 s = "("; | |
835 foreach (i, element; elements) | |
836 { | |
837 if (i) | |
838 s ~= ','; | |
839 s ~= element.toString(); | |
840 } | |
841 s ~= ")"; | |
842 return s; | |
843 } | |
844 | |
845 int opEquals(Object o) | |
846 { | |
847 if (this is o) | |
848 return 1; | |
849 | |
850 auto t = cast(TypeInfo_Tuple)o; | |
851 if (t && elements.length == t.elements.length) | |
852 { | |
853 for (size_t i = 0; i < elements.length; i++) | |
854 { | |
855 if (elements[i] != t.elements[i]) | |
856 return 0; | |
857 } | |
858 return 1; | |
859 } | |
860 return 0; | |
861 } | |
862 | |
863 hash_t getHash(void *p) | |
864 { | |
865 assert(0); | |
866 } | |
867 | |
868 int equals(void *p1, void *p2) | |
869 { | |
870 assert(0); | |
871 } | |
872 | |
873 int compare(void *p1, void *p2) | |
874 { | |
875 assert(0); | |
876 } | |
877 | |
878 size_t tsize() | |
879 { | |
880 assert(0); | |
881 } | |
882 | |
883 void swap(void *p1, void *p2) | |
884 { | |
885 assert(0); | |
886 } | |
887 } | |
888 | |
889 class Exception : Object | |
890 { | |
891 char[] msg; | |
892 char[] file; | |
893 size_t line; | |
894 Exception next; | |
895 | |
896 this(char[] msg, Exception next = null) | |
897 { | |
898 this.msg = msg; | |
899 this.next = next; | |
900 } | |
901 | |
902 this(char[] msg, char[] file, size_t line, Exception next = null) | |
903 { | |
904 this(msg, next); | |
905 this.file = file; | |
906 this.line = line; | |
907 } | |
908 | |
909 char[] toString() | |
910 { | |
911 return msg; | |
912 } | |
913 } | |
914 | |
915 | |
916 //////////////////////////////////////////////////////////////////////////////// | |
917 // ModuleInfo | |
918 //////////////////////////////////////////////////////////////////////////////// | |
919 | |
920 | |
921 enum | |
922 { | |
923 MIctorstart = 1, // we've started constructing it | |
924 MIctordone = 2, // finished construction | |
925 MIstandalone = 4, // module ctor does not depend on other module | |
926 // ctors being done first | |
927 MIhasictor = 8, // has ictor member | |
928 } | |
929 | |
930 | |
931 class ModuleInfo | |
932 { | |
933 char[] name; | |
934 ModuleInfo[] importedModules; | |
935 ClassInfo[] localClasses; | |
936 uint flags; | |
937 | |
938 void function() ctor; // module static constructor (order dependent) | |
939 void function() dtor; // module static destructor | |
940 void function() unitTest; // module unit tests | |
941 | |
942 void* xgetMembers; // module getMembers() function | |
943 | |
944 void function() ictor; // module static constructor (order independent) | |
945 | |
946 static int opApply( int delegate( inout ModuleInfo ) dg ) | |
947 { | |
948 int ret = 0; | |
949 | |
950 foreach( m; _moduleinfo_array ) | |
951 { | |
952 ret = dg( m ); | |
953 if( ret ) | |
954 break; | |
955 } | |
956 return ret; | |
957 } | |
958 } | |
959 | |
960 | |
961 // Win32: this gets initialized by minit.asm | |
962 // linux: this gets initialized in _moduleCtor() | |
963 extern (C) ModuleInfo[] _moduleinfo_array; | |
964 | |
965 | |
966 version (linux) | |
967 { | |
968 // This linked list is created by a compiler generated function inserted | |
969 // into the .ctor list by the compiler. | |
970 struct ModuleReference | |
971 { | |
972 ModuleReference* next; | |
973 ModuleInfo mod; | |
974 } | |
975 | |
976 extern (C) ModuleReference* _Dmodule_ref; // start of linked list | |
977 } | |
978 | |
979 ModuleInfo[] _moduleinfo_dtors; | |
980 uint _moduleinfo_dtors_i; | |
981 | |
982 // Register termination function pointers | |
983 extern (C) int _fatexit(void *); | |
984 | |
985 /** | |
986 * Initialize the modules. | |
987 */ | |
988 | |
989 extern (C) void _moduleCtor() | |
990 { | |
991 debug(PRINTF) printf("_moduleCtor()\n"); | |
992 version (linux) | |
993 { | |
994 int len = 0; | |
995 ModuleReference *mr; | |
996 | |
997 for (mr = _Dmodule_ref; mr; mr = mr.next) | |
998 len++; | |
999 _moduleinfo_array = new ModuleInfo[len]; | |
1000 len = 0; | |
1001 for (mr = _Dmodule_ref; mr; mr = mr.next) | |
1002 { _moduleinfo_array[len] = mr.mod; | |
1003 len++; | |
1004 } | |
1005 } | |
1006 | |
1007 version (Win32) | |
1008 { | |
1009 // Ensure module destructors also get called on program termination | |
1010 //_fatexit(&_STD_moduleDtor); | |
1011 } | |
1012 | |
1013 _moduleinfo_dtors = new ModuleInfo[_moduleinfo_array.length]; | |
1014 debug(PRINTF) printf("_moduleinfo_dtors = x%x\n", cast(void *)_moduleinfo_dtors); | |
1015 _moduleIndependentCtors(); | |
1016 _moduleCtor2(_moduleinfo_array, 0); | |
1017 } | |
1018 | |
1019 extern (C) void _moduleIndependentCtors() | |
1020 { | |
1021 debug(PRINTF) printf("_moduleIndependentCtors()\n"); | |
1022 foreach (m; _moduleinfo_array) | |
1023 { | |
1024 if (m && m.flags & MIhasictor && m.ictor) | |
1025 { | |
1026 (*m.ictor)(); | |
1027 } | |
1028 } | |
1029 } | |
1030 | |
1031 void _moduleCtor2(ModuleInfo[] mi, int skip) | |
1032 { | |
1033 debug(PRINTF) printf("_moduleCtor2(): %d modules\n", mi.length); | |
1034 for (uint i = 0; i < mi.length; i++) | |
1035 { | |
1036 ModuleInfo m = mi[i]; | |
1037 | |
1038 debug(PRINTF) printf("\tmodule[%d] = '%p'\n", i, m); | |
1039 if (!m) | |
1040 continue; | |
1041 debug(PRINTF) printf("\tmodule[%d] = '%.*s'\n", i, m.name); | |
1042 if (m.flags & MIctordone) | |
1043 continue; | |
1044 debug(PRINTF) printf("\tmodule[%d] = '%.*s', m = x%x\n", i, m.name, m); | |
1045 | |
1046 if (m.ctor || m.dtor) | |
1047 { | |
1048 if (m.flags & MIctorstart) | |
1049 { if (skip || m.flags & MIstandalone) | |
1050 continue; | |
1051 throw new Exception( "Cyclic dependency in module " ~ m.name ); | |
1052 } | |
1053 | |
1054 m.flags |= MIctorstart; | |
1055 _moduleCtor2(m.importedModules, 0); | |
1056 if (m.ctor) | |
1057 (*m.ctor)(); | |
1058 m.flags &= ~MIctorstart; | |
1059 m.flags |= MIctordone; | |
1060 | |
1061 // Now that construction is done, register the destructor | |
1062 //printf("\tadding module dtor x%x\n", m); | |
1063 assert(_moduleinfo_dtors_i < _moduleinfo_dtors.length); | |
1064 _moduleinfo_dtors[_moduleinfo_dtors_i++] = m; | |
1065 } | |
1066 else | |
1067 { | |
1068 m.flags |= MIctordone; | |
1069 _moduleCtor2(m.importedModules, 1); | |
1070 } | |
1071 } | |
1072 } | |
1073 | |
1074 /** | |
1075 * Destruct the modules. | |
1076 */ | |
1077 | |
1078 // Starting the name with "_STD" means under linux a pointer to the | |
1079 // function gets put in the .dtors segment. | |
1080 | |
1081 extern (C) void _moduleDtor() | |
1082 { | |
1083 debug(PRINTF) printf("_moduleDtor(): %d modules\n", _moduleinfo_dtors_i); | |
1084 | |
1085 for (uint i = _moduleinfo_dtors_i; i-- != 0;) | |
1086 { | |
1087 ModuleInfo m = _moduleinfo_dtors[i]; | |
1088 | |
1089 debug(PRINTF) printf("\tmodule[%d] = '%.*s', x%x\n", i, m.name, m); | |
1090 if (m.dtor) | |
1091 { | |
1092 (*m.dtor)(); | |
1093 } | |
1094 } | |
1095 debug(PRINTF) printf("_moduleDtor() done\n"); | |
1096 } | |
1097 | |
1098 //////////////////////////////////////////////////////////////////////////////// | |
1099 // Monitor | |
1100 //////////////////////////////////////////////////////////////////////////////// | |
1101 | |
1102 alias Object.Monitor IMonitor; | |
1103 | |
1104 struct Monitor | |
1105 { | |
1106 IMonitor impl; | |
1107 /* stuff */ | |
1108 } | |
1109 | |
1110 Monitor* getMonitor(Object h) | |
1111 { | |
1112 return cast(Monitor*) (cast(void**) h)[1]; | |
1113 } | |
1114 | |
1115 void setMonitor(Object h, Monitor* m) | |
1116 { | |
1117 (cast(void**) h)[1] = m; | |
1118 } | |
1119 | |
1120 extern (C) void _d_monitor_create(Object); | |
1121 extern (C) void _d_monitor_destroy(Object); | |
1122 extern (C) void _d_monitor_lock(Object); | |
1123 extern (C) int _d_monitor_unlock(Object); | |
1124 | |
1125 extern (C) void _d_monitordelete(Object h, bool det) | |
1126 { | |
1127 Monitor* m = getMonitor(h); | |
1128 | |
1129 if (m !is null) | |
1130 { | |
1131 IMonitor i = m.impl; | |
1132 if (i is null) | |
1133 { | |
1134 _d_monitor_destroy(h); | |
1135 setMonitor(h, null); | |
1136 return; | |
1137 } | |
1138 if (det && (cast(void*) i) !is (cast(void*) h)) | |
1139 delete i; | |
1140 setMonitor(h, null); | |
1141 } | |
1142 } | |
1143 | |
1144 extern (C) void _d_monitorenter(Object h) | |
1145 { | |
1146 Monitor* m = getMonitor(h); | |
1147 | |
1148 if (m is null) | |
1149 { | |
1150 _d_monitor_create(h); | |
1151 m = getMonitor(h); | |
1152 } | |
1153 | |
1154 IMonitor i = m.impl; | |
1155 | |
1156 if (i is null) | |
1157 { | |
1158 _d_monitor_lock(h); | |
1159 return; | |
1160 } | |
1161 i.lock(); | |
1162 } | |
1163 | |
1164 extern (C) void _d_monitorexit(Object h) | |
1165 { | |
1166 Monitor* m = getMonitor(h); | |
1167 IMonitor i = m.impl; | |
1168 | |
1169 if (i is null) | |
1170 { | |
1171 _d_monitor_unlock(h); | |
1172 return; | |
1173 } | |
1174 i.unlock(); | |
1175 } |