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 */