Mercurial > projects > ddmd
comparison dmd/TObject.d @ 178:e3afd1303184
Many small bugs fixed
Made all classes derive from TObject to detect memory leaks (functionality is disabled for now)
Began work on overriding backend memory allocations (to avoid memory leaks)
author | korDen |
---|---|
date | Sun, 17 Oct 2010 07:42:00 +0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
177:1475fd394c9e | 178:e3afd1303184 |
---|---|
1 module dmd.TObject; | |
2 /* | |
3 import core.runtime; | |
4 import core.stdc.stdio; | |
5 import core.stdc.string; | |
6 import core.stdc.stdlib; | |
7 | |
8 import dmd.TObject; | |
9 | |
10 import core.sys.windows.windows; | |
11 import core.sys.windows.codeview; | |
12 import core.demangle; | |
13 import core.memory; | |
14 import core.stdc.stdlib; | |
15 | |
16 version = TrackArray; | |
17 | |
18 version (TrackList) { | |
19 enum mNull = TObject.pack(0); | |
20 __gshared size_t mHead = mNull; | |
21 } else version (TrackArray) { | |
22 __gshared size_t[] objects; | |
23 } | |
24 */ | |
25 class TObject | |
26 { | |
27 void register() | |
28 { | |
29 } | |
30 | |
31 void forceRegister() | |
32 { | |
33 } | |
34 | |
35 /* | |
36 this() | |
37 { | |
38 register(); | |
39 } | |
40 | |
41 ~this() | |
42 { | |
43 size_t mThis = pack(this); | |
44 | |
45 version (TrackList) { | |
46 if (mPrev != mNull) { | |
47 unpack(mPrev).mNext = mNext; | |
48 } else { | |
49 assert(mHead == mThis); | |
50 mHead = mNext; | |
51 } | |
52 | |
53 if (mNext != mNull) { | |
54 unpack(mNext).mPrev = mPrev; | |
55 } | |
56 } else version (TrackArray) { | |
57 foreach (i, o; objects) { | |
58 if (o == mThis) { | |
59 size_t newLen = objects.length - 1; | |
60 objects[i] = objects[newLen]; | |
61 objects.length = newLen; | |
62 | |
63 alloc = cast(void*)-1; | |
64 return; | |
65 } | |
66 } | |
67 } | |
68 } | |
69 | |
70 version (TrackList) { | |
71 size_t mPrev; | |
72 size_t mNext; | |
73 } | |
74 | |
75 void* alloc; | |
76 | |
77 static TObject unpack(size_t m) | |
78 { | |
79 m &= ~(1 << 31); | |
80 return cast(TObject)cast(void*)m; | |
81 } | |
82 | |
83 static size_t pack(size_t m) | |
84 { | |
85 return m |= (1 << 31); | |
86 } | |
87 | |
88 static size_t pack(TObject o) | |
89 { | |
90 return pack(cast(size_t)cast(void*)o); | |
91 } | |
92 | |
93 void forceRegister() | |
94 { | |
95 version (TrackList) { | |
96 alloc = alloc_point(); | |
97 size_t mThis = pack(this); | |
98 | |
99 mNext = mHead; | |
100 if (mHead != mNull) { | |
101 unpack(mHead).mPrev = mThis; | |
102 } | |
103 | |
104 mPrev = mNull; | |
105 mHead = mThis; | |
106 } else version (TrackArray) { | |
107 alloc = alloc_point(); | |
108 objects ~= pack(this); | |
109 } | |
110 } | |
111 | |
112 void register() | |
113 { | |
114 if (alloc !is null) return; | |
115 forceRegister(); | |
116 } | |
117 | |
118 static void dump() | |
119 { | |
120 int[void*] allocStat; | |
121 | |
122 version (TrackList) { | |
123 auto o = unpack(mHead); | |
124 while (o !is null) { | |
125 allocStat[o.alloc]++; | |
126 o = unpack(o.mNext); | |
127 } | |
128 } else version (TrackArray) { | |
129 foreach (i, m; objects) { | |
130 allocStat[unpack(m).alloc]++; | |
131 } | |
132 } | |
133 | |
134 FILE* f = fopen("alloc_stat.txt", "wb"); | |
135 if (f is null) return; | |
136 | |
137 StackFrameInfo* frame = void; | |
138 DebugImage* imageList, image = void; | |
139 char[255] buffer = void; | |
140 | |
141 MEMORY_BASIC_INFORMATION mbi = void; | |
142 | |
143 void resolve(const(void)* c) { | |
144 StackFrameInfo frame; | |
145 frame.va = cast(void*)c; | |
146 | |
147 // mbi.Allocation base is the handle to stack frame's module | |
148 VirtualQuery(frame.va, &mbi, MEMORY_BASIC_INFORMATION.sizeof); | |
149 if (!mbi.AllocationBase) return; | |
150 | |
151 image = imageList; | |
152 while(image) { | |
153 if (image.baseAddress == cast(size_t)mbi.AllocationBase) break; | |
154 image = image.next; | |
155 } | |
156 | |
157 if (!image) { | |
158 image = new DebugImage; | |
159 | |
160 with (*image) { | |
161 next = imageList; | |
162 imageList = image; | |
163 baseAddress = cast(size_t)mbi.AllocationBase; | |
164 | |
165 uint len = GetModuleFileNameA(cast(HMODULE)baseAddress, buffer.ptr, buffer.length); | |
166 moduleName = buffer[0 .. len].idup; | |
167 | |
168 if (len != 0) { | |
169 exeModule = new PEImage(moduleName); | |
170 rvaOffset = baseAddress + exeModule.codeOffset; | |
171 debugInfo = exeModule.debugInfo; | |
172 } | |
173 } | |
174 } | |
175 | |
176 frame.moduleName = image.moduleName; | |
177 | |
178 size_t va = cast(size_t)frame.va; | |
179 | |
180 if (image.debugInfo) with (image.debugInfo) { | |
181 uint rva = va - image.rvaOffset; | |
182 | |
183 frame.symbol = ResolveSymbol(rva); | |
184 frame.fileLine = ResolveFileLine(rva); | |
185 } | |
186 | |
187 auto s = image.exeModule.closestSymbol(va); | |
188 printf("%.*s\n", s); | |
189 auto symbol = demangle(s.symbol); | |
190 | |
191 if (frame.fileLine.file.length != 0) { | |
192 fprintf(f, "%.*s %.*s:%d\n", symbol, frame.fileLine.file, frame.fileLine.line); | |
193 // } else { | |
194 // if (symbol.length != 0) { | |
195 // fprintf(f, "%.*s", symbol); | |
196 // } | |
197 } | |
198 } | |
199 | |
200 while (imageList) { | |
201 image = imageList.next; | |
202 delete imageList.debugInfo; | |
203 delete imageList.exeModule; | |
204 delete imageList; | |
205 imageList = image; | |
206 } | |
207 | |
208 int max = 0; | |
209 int total = 0; | |
210 fprintf(f, "%d\n", allocStat.length); | |
211 foreach (alloc, count; allocStat) { | |
212 resolve(alloc); | |
213 | |
214 fprintf(f, "count: %d\n\n", count); | |
215 if (count > max) max = count; | |
216 total += count; | |
217 } | |
218 fprintf(f, "max: %d\n\n", max); | |
219 fprintf(f, "total: %d\n\n", total); | |
220 fclose(f); | |
221 } | |
222 */ | |
223 } | |
224 /* | |
225 void* alloc_point() | |
226 { | |
227 void** bp = void; | |
228 | |
229 asm { | |
230 mov bp, EBP; | |
231 } | |
232 | |
233 bp = cast(void**)*bp; | |
234 bp = cast(void**)*bp; | |
235 bp = cast(void**)*bp; | |
236 return *(bp + 1); | |
237 } | |
238 | |
239 void callstack_print(FILE* f, void*[] callstack) | |
240 { | |
241 char** framelist = backtrace_symbols(callstack.ptr, callstack.length); | |
242 for( int i = 0; i < callstack.length; ++i ) | |
243 { | |
244 auto line = framelist[i]; | |
245 if (strcmp(line, "<no debug info found>") == 0) { | |
246 continue; | |
247 } | |
248 fwrite(line, 1, strlen(line), f); | |
249 fwrite("\n".ptr, 1, 1, f); | |
250 } | |
251 free(framelist); | |
252 } | |
253 */ |