comparison druntime/src/compiler/ldc/memory.d @ 759:d3eb054172f9

Added copy of druntime from DMD 2.020 modified for LDC.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Tue, 11 Nov 2008 01:52:37 +0100
parents
children
comparison
equal deleted inserted replaced
758:f04dde6e882c 759:d3eb054172f9
1 /**
2 * This module exposes functionality for inspecting and manipulating memory.
3 *
4 * Copyright: Copyright (C) 2005-2006 Digital Mars, www.digitalmars.com.
5 * All rights reserved.
6 * License:
7 * This software is provided 'as-is', without any express or implied
8 * warranty. In no event will the authors be held liable for any damages
9 * arising from the use of this software.
10 *
11 * Permission is granted to anyone to use this software for any purpose,
12 * including commercial applications, and to alter it and redistribute it
13 * freely, in both source and binary form, subject to the following
14 * restrictions:
15 *
16 * o The origin of this software must not be misrepresented; you must not
17 * claim that you wrote the original software. If you use this software
18 * in a product, an acknowledgment in the product documentation would be
19 * appreciated but is not required.
20 * o Altered source versions must be plainly marked as such, and must not
21 * be misrepresented as being the original software.
22 * o This notice may not be removed or altered from any source
23 * distribution.
24 * Authors: Walter Bright, Sean Kelly
25 */
26 module memory;
27
28 version = GC_Use_Dynamic_Ranges;
29
30 // does Posix suffice?
31 version(Posix)
32 {
33 version = GC_Use_Data_Proc_Maps;
34 }
35
36 version(GC_Use_Data_Proc_Maps)
37 {
38 version(Posix) {} else {
39 static assert(false, "Proc Maps only supported on Posix systems");
40 }
41
42 version( D_Version2 )
43 {
44 private import stdc.posix.unistd;
45 private import stdc.posix.fcntl;
46 private import stdc.string;
47 }
48 else
49 {
50 private import tango.stdc.posix.unistd;
51 private import tango.stdc.posix.fcntl;
52 private import tango.stdc.string;
53 }
54
55 version = GC_Use_Dynamic_Ranges;
56 }
57
58 private
59 {
60 version( linux )
61 {
62 //version = SimpleLibcStackEnd;
63
64 version( SimpleLibcStackEnd )
65 {
66 extern (C) extern void* __libc_stack_end;
67 }
68 else
69 {
70 version( D_Version2 )
71 import stdc.posix.dlfcn;
72 else
73 import tango.stdc.posix.dlfcn;
74 }
75 }
76 version(LDC)
77 {
78 pragma(intrinsic, "llvm.frameaddress")
79 {
80 void* llvm_frameaddress(uint level=0);
81 }
82 }
83 }
84
85
86 /**
87 *
88 */
89 extern (C) void* rt_stackBottom()
90 {
91 version( Win32 )
92 {
93 void* bottom;
94 asm
95 {
96 mov EAX, FS:4;
97 mov bottom, EAX;
98 }
99 return bottom;
100 }
101 else version( linux )
102 {
103 version( SimpleLibcStackEnd )
104 {
105 return __libc_stack_end;
106 }
107 else
108 {
109 // See discussion: http://autopackage.org/forums/viewtopic.php?t=22
110 static void** libc_stack_end;
111
112 if( libc_stack_end == libc_stack_end.init )
113 {
114 void* handle = dlopen( null, RTLD_NOW );
115 libc_stack_end = cast(void**) dlsym( handle, "__libc_stack_end" );
116 dlclose( handle );
117 }
118 return *libc_stack_end;
119 }
120 }
121 else version( darwin )
122 {
123 // darwin has a fixed stack bottom
124 return cast(void*) 0xc0000000;
125 }
126 else
127 {
128 static assert( false, "Operating system not supported." );
129 }
130 }
131
132
133 /**
134 *
135 */
136 extern (C) void* rt_stackTop()
137 {
138 version(LDC)
139 {
140 return llvm_frameaddress();
141 }
142 else version( D_InlineAsm_X86 )
143 {
144 asm
145 {
146 naked;
147 mov EAX, ESP;
148 ret;
149 }
150 }
151 else
152 {
153 static assert( false, "Architecture not supported." );
154 }
155 }
156
157
158 private
159 {
160 version( Win32 )
161 {
162 extern (C)
163 {
164 extern int _data_start__;
165 extern int _bss_end__;
166
167 alias _data_start__ Data_Start;
168 alias _bss_end__ Data_End;
169 }
170 }
171 else version( linux )
172 {
173 extern (C)
174 {
175 extern int _data;
176 extern int __data_start;
177 extern int _end;
178 extern int _data_start__;
179 extern int _data_end__;
180 extern int _bss_start__;
181 extern int _bss_end__;
182 extern int __fini_array_end;
183 }
184
185 alias __data_start Data_Start;
186 alias _end Data_End;
187 }
188
189 version( GC_Use_Dynamic_Ranges )
190 {
191 version( D_Version2 )
192 private import stdc.stdlib;
193 else
194 private import tango.stdc.stdlib;
195
196 struct DataSeg
197 {
198 void* beg;
199 void* end;
200 }
201
202 DataSeg* allSegs = null;
203 size_t numSegs = 0;
204
205 extern (C) void _d_gc_add_range( void* beg, void* end )
206 {
207 void* ptr = realloc( allSegs, (numSegs + 1) * DataSeg.sizeof );
208
209 if( ptr ) // if realloc fails, we have problems
210 {
211 allSegs = cast(DataSeg*) ptr;
212 allSegs[numSegs].beg = beg;
213 allSegs[numSegs].end = end;
214 numSegs++;
215 }
216 }
217
218 extern (C) void _d_gc_remove_range( void* beg )
219 {
220 for( size_t pos = 0; pos < numSegs; ++pos )
221 {
222 if( beg == allSegs[pos].beg )
223 {
224 while( ++pos < numSegs )
225 {
226 allSegs[pos-1] = allSegs[pos];
227 }
228 numSegs--;
229 return;
230 }
231 }
232 }
233 }
234
235 alias void delegate( void*, void* ) scanFn;
236
237 void* dataStart, dataEnd;
238 }
239
240
241 /**
242 *
243 */
244 extern (C) void rt_scanStaticData( scanFn scan )
245 {
246 scan( dataStart, dataEnd );
247
248 version( GC_Use_Dynamic_Ranges )
249 {
250 for( size_t pos = 0; pos < numSegs; ++pos )
251 {
252 scan( allSegs[pos].beg, allSegs[pos].end );
253 }
254 }
255 }
256
257 void initStaticDataPtrs()
258 {
259 version( D_Version2 )
260 enum { int S = (void*).sizeof }
261 else
262 const int S = (void*).sizeof;
263
264 // Can't assume the input addresses are word-aligned
265 static void* adjust_up( void* p )
266 {
267 return p + ((S - (cast(size_t)p & (S-1))) & (S-1)); // cast ok even if 64-bit
268 }
269
270 static void * adjust_down( void* p )
271 {
272 return p - (cast(size_t) p & (S-1));
273 }
274
275 version( Win32 )
276 {
277 dataStart = adjust_up( &Data_Start );
278 dataEnd = adjust_down( &Data_End );
279 }
280 else version( GC_Use_Data_Proc_Maps )
281 {
282 // TODO: Exclude zero-mapped regions
283
284 int fd = open("/proc/self/maps", O_RDONLY);
285 int count; // %% need to configure ret for read..
286 char buf[2024];
287 char* p;
288 char* e;
289 char* s;
290 void* start;
291 void* end;
292
293 p = buf.ptr;
294 if (fd != -1)
295 {
296 while ( (count = read(fd, p, buf.sizeof - (p - buf.ptr))) > 0 )
297 {
298 e = p + count;
299 p = buf.ptr;
300 while (true)
301 {
302 s = p;
303 while (p < e && *p != '\n')
304 p++;
305 if (p < e)
306 {
307 // parse the entry in [s, p)
308 static if( S == 4 )
309 {
310 enum Ofs
311 {
312 Write_Prot = 19,
313 Start_Addr = 0,
314 End_Addr = 9,
315 Addr_Len = 8,
316 }
317 }
318 else static if( S == 8 )
319 {
320 enum Ofs
321 {
322 Write_Prot = 35,
323 Start_Addr = 0,
324 End_Addr = 9,
325 Addr_Len = 17,
326 }
327 }
328 else
329 {
330 static assert( false );
331 }
332
333 // %% this is wrong for 64-bit:
334 // uint strtoul(char *,char **,int);
335
336 if( s[Ofs.Write_Prot] == 'w' )
337 {
338 s[Ofs.Start_Addr + Ofs.Addr_Len] = '\0';
339 s[Ofs.End_Addr + Ofs.Addr_Len] = '\0';
340 start = cast(void*) strtoul(s + Ofs.Start_Addr, null, 16);
341 end = cast(void*) strtoul(s + Ofs.End_Addr, null, 16);
342
343 // 1. Exclude anything overlapping [dataStart, dataEnd)
344 // 2. Exclude stack
345 if ( ( !dataEnd ||
346 !( dataStart >= start && dataEnd <= end ) ) &&
347 !( &buf[0] >= start && &buf[0] < end ) )
348 {
349 // we already have static data from this region. anything else
350 // is heap (%% check)
351 debug (ProcMaps) printf("Adding map range %p 0%p\n", start, end);
352 _d_gc_add_range(start, end);
353 }
354 }
355 p++;
356 }
357 else
358 {
359 count = p - s;
360 memmove(buf.ptr, s, count);
361 p = buf.ptr + count;
362 break;
363 }
364 }
365 }
366 close(fd);
367 }
368 }
369 else version(linux)
370 {
371 dataStart = adjust_up( &Data_Start );
372 dataEnd = adjust_down( &Data_End );
373 }
374 else
375 {
376 static assert( false, "Operating system not supported." );
377 }
378 }