Mercurial > projects > ldc
annotate tango/lib/compiler/llvmdc/lifetime.d @ 286:a3b7c19c866c trunk
[svn r307] Fixed: multidimensional new expressions now work. Eg.:
auto ma = new int[][] (3,9);
author | lindquist |
---|---|
date | Sat, 21 Jun 2008 04:47:14 +0200 |
parents | 23d0d9855cad |
children | 2b72433d5c8c |
rev | line source |
---|---|
132 | 1 /** |
2 * This module contains all functions related to an object's lifetime: | |
3 * allocation, resizing, deallocation, and finalization. | |
4 * | |
5 * Copyright: Copyright (C) 2004-2007 Digital Mars, www.digitalmars.com. | |
6 * All rights reserved. | |
7 * License: | |
8 * This software is provided 'as-is', without any express or implied | |
9 * warranty. In no event will the authors be held liable for any damages | |
10 * arising from the use of this software. | |
11 * | |
12 * Permission is granted to anyone to use this software for any purpose, | |
13 * including commercial applications, and to alter it and redistribute it | |
14 * freely, in both source and binary form, subject to the following | |
15 * restrictions: | |
16 * | |
17 * o The origin of this software must not be misrepresented; you must not | |
18 * claim that you wrote the original software. If you use this software | |
19 * in a product, an acknowledgment in the product documentation would be | |
20 * appreciated but is not required. | |
21 * o Altered source versions must be plainly marked as such, and must not | |
22 * be misrepresented as being the original software. | |
23 * o This notice may not be removed or altered from any source | |
24 * distribution. | |
25 * Authors: Walter Bright, Sean Kelly, Tomas Lindquist Olsen | |
26 */ | |
27 module lifetime; | |
28 | |
133
44a95ac7368a
[svn r137] Many fixes towards tango.io.Console working, but not quite there yet...
lindquist
parents:
132
diff
changeset
|
29 //debug=PRINTF; |
137 | 30 //debug=PRINTF2; |
132 | 31 |
237
a168a2c3ea48
[svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents:
212
diff
changeset
|
32 // we're not allowed to jump out of asm blocks |
a168a2c3ea48
[svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents:
212
diff
changeset
|
33 //version(D_InlineAsm_X86) version = Asm86; |
a168a2c3ea48
[svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents:
212
diff
changeset
|
34 |
132 | 35 private |
36 { | |
37 import tango.stdc.stdlib; | |
38 import tango.stdc.string; | |
39 import tango.stdc.stdarg; | |
40 debug(PRINTF) import tango.stdc.stdio; | |
133
44a95ac7368a
[svn r137] Many fixes towards tango.io.Console working, but not quite there yet...
lindquist
parents:
132
diff
changeset
|
41 else debug(PRINTF2) import tango.stdc.stdio; |
132 | 42 } |
43 | |
44 | |
45 private | |
46 { | |
47 enum BlkAttr : uint | |
48 { | |
49 FINALIZE = 0b0000_0001, | |
50 NO_SCAN = 0b0000_0010, | |
51 NO_MOVE = 0b0000_0100, | |
52 ALL_BITS = 0b1111_1111 | |
53 } | |
54 | |
55 struct BlkInfo | |
56 { | |
57 void* base; | |
58 size_t size; | |
59 uint attr; | |
60 } | |
61 | |
62 extern (C) uint gc_getAttr( void* p ); | |
63 extern (C) uint gc_setAttr( void* p, uint a ); | |
64 extern (C) uint gc_clrAttr( void* p, uint a ); | |
65 | |
66 extern (C) void* gc_malloc( size_t sz, uint ba = 0 ); | |
67 extern (C) void* gc_calloc( size_t sz, uint ba = 0 ); | |
68 extern (C) size_t gc_extend( void* p, size_t mx, size_t sz ); | |
69 extern (C) void gc_free( void* p ); | |
70 | |
71 extern (C) void* gc_addrOf( void* p ); | |
72 extern (C) size_t gc_sizeOf( void* p ); | |
73 extern (C) BlkInfo gc_query( void* p ); | |
74 | |
75 extern (C) bool onCollectResource( Object o ); | |
76 extern (C) void onFinalizeError( ClassInfo c, Exception e ); | |
77 extern (C) void onOutOfMemoryError(); | |
78 | |
79 extern (C) void _d_monitordelete(Object h, bool det = true); | |
80 | |
81 enum | |
82 { | |
83 PAGESIZE = 4096 | |
84 } | |
85 } | |
86 | |
87 | |
88 /** | |
89 * | |
90 */ | |
91 extern (C) Object _d_newclass(ClassInfo ci) | |
92 { | |
93 void* p; | |
94 | |
137 | 95 debug(PRINTF2) printf("_d_newclass(ci = %p, %s)\n", ci, cast(char *)ci.name.ptr); |
133
44a95ac7368a
[svn r137] Many fixes towards tango.io.Console working, but not quite there yet...
lindquist
parents:
132
diff
changeset
|
96 /+ |
132 | 97 if (ci.flags & 1) // if COM object |
98 { /* COM objects are not garbage collected, they are reference counted | |
99 * using AddRef() and Release(). They get free'd by C's free() | |
100 * function called by Release() when Release()'s reference count goes | |
101 * to zero. | |
102 */ | |
103 p = tango.stdc.stdlib.malloc(ci.init.length); | |
104 if (!p) | |
105 onOutOfMemoryError(); | |
106 } | |
107 else | |
133
44a95ac7368a
[svn r137] Many fixes towards tango.io.Console working, but not quite there yet...
lindquist
parents:
132
diff
changeset
|
108 +/ |
132 | 109 { |
110 p = gc_malloc(ci.init.length, | |
111 BlkAttr.FINALIZE | (ci.flags & 2 ? BlkAttr.NO_SCAN : 0)); | |
133
44a95ac7368a
[svn r137] Many fixes towards tango.io.Console working, but not quite there yet...
lindquist
parents:
132
diff
changeset
|
112 debug(PRINTF2) printf(" p = %p\n", p); |
132 | 113 } |
114 | |
137 | 115 debug(PRINTF2) |
132 | 116 { |
117 printf("p = %p\n", p); | |
137 | 118 printf("ci = %p, ci.init = %p, len = %d\n", ci, ci.init.ptr, ci.init.length); |
119 printf("vptr = %p\n", *cast(void**) ci.init.ptr); | |
120 printf("vtbl[0] = %p\n", (*cast(void***) ci.init.ptr)[0]); | |
121 printf("vtbl[1] = %p\n", (*cast(void***) ci.init.ptr)[1]); | |
122 printf("init[0] = %p\n", (cast(uint**) ci.init.ptr)[0]); | |
123 printf("init[1] = %p\n", (cast(uint**) ci.init.ptr)[1]); | |
124 printf("init[2] = %p\n", (cast(uint**) ci.init.ptr)[2]); | |
125 printf("init[3] = %p\n", (cast(uint**) ci.init.ptr)[3]); | |
126 printf("init[4] = %p\n", (cast(uint**) ci.init.ptr)[4]); | |
132 | 127 } |
128 | |
129 // initialize it | |
133
44a95ac7368a
[svn r137] Many fixes towards tango.io.Console working, but not quite there yet...
lindquist
parents:
132
diff
changeset
|
130 // llvmdc does this inline |
44a95ac7368a
[svn r137] Many fixes towards tango.io.Console working, but not quite there yet...
lindquist
parents:
132
diff
changeset
|
131 //(cast(byte*) p)[0 .. ci.init.length] = ci.init[]; |
132 | 132 |
133 debug(PRINTF) printf("initialization done\n"); | |
134 return cast(Object) p; | |
135 } | |
136 | |
137 /** | |
138 * | |
139 */ | |
209
c4c9b4ac021b
[svn r225] Fixed: delete expressions no longer use llvm's free instruction, which crashes on a GC provided pointer.
lindquist
parents:
203
diff
changeset
|
140 extern (C) void _d_delinterface(void* p) |
132 | 141 { |
209
c4c9b4ac021b
[svn r225] Fixed: delete expressions no longer use llvm's free instruction, which crashes on a GC provided pointer.
lindquist
parents:
203
diff
changeset
|
142 if (p) |
132 | 143 { |
209
c4c9b4ac021b
[svn r225] Fixed: delete expressions no longer use llvm's free instruction, which crashes on a GC provided pointer.
lindquist
parents:
203
diff
changeset
|
144 Interface* pi = **cast(Interface ***)p; |
c4c9b4ac021b
[svn r225] Fixed: delete expressions no longer use llvm's free instruction, which crashes on a GC provided pointer.
lindquist
parents:
203
diff
changeset
|
145 Object o = cast(Object)(p - pi.offset); |
132 | 146 |
209
c4c9b4ac021b
[svn r225] Fixed: delete expressions no longer use llvm's free instruction, which crashes on a GC provided pointer.
lindquist
parents:
203
diff
changeset
|
147 _d_delclass(o); |
c4c9b4ac021b
[svn r225] Fixed: delete expressions no longer use llvm's free instruction, which crashes on a GC provided pointer.
lindquist
parents:
203
diff
changeset
|
148 //*p = null; |
132 | 149 } |
150 } | |
151 | |
152 // used for deletion | |
153 private extern (D) alias void function(Object) fp_t; | |
154 | |
155 | |
156 /** | |
157 * | |
158 */ | |
209
c4c9b4ac021b
[svn r225] Fixed: delete expressions no longer use llvm's free instruction, which crashes on a GC provided pointer.
lindquist
parents:
203
diff
changeset
|
159 extern (C) void _d_delclass(Object p) |
132 | 160 { |
209
c4c9b4ac021b
[svn r225] Fixed: delete expressions no longer use llvm's free instruction, which crashes on a GC provided pointer.
lindquist
parents:
203
diff
changeset
|
161 if (p) |
132 | 162 { |
209
c4c9b4ac021b
[svn r225] Fixed: delete expressions no longer use llvm's free instruction, which crashes on a GC provided pointer.
lindquist
parents:
203
diff
changeset
|
163 debug(PRINTF) printf("_d_delclass(%p)\n", p); |
132 | 164 |
209
c4c9b4ac021b
[svn r225] Fixed: delete expressions no longer use llvm's free instruction, which crashes on a GC provided pointer.
lindquist
parents:
203
diff
changeset
|
165 ClassInfo **pc = cast(ClassInfo **)p; |
132 | 166 if (*pc) |
167 { | |
168 ClassInfo c = **pc; | |
169 | |
209
c4c9b4ac021b
[svn r225] Fixed: delete expressions no longer use llvm's free instruction, which crashes on a GC provided pointer.
lindquist
parents:
203
diff
changeset
|
170 rt_finalize(cast(void*) p); |
132 | 171 |
172 if (c.deallocator) | |
173 { | |
174 fp_t fp = cast(fp_t)c.deallocator; | |
209
c4c9b4ac021b
[svn r225] Fixed: delete expressions no longer use llvm's free instruction, which crashes on a GC provided pointer.
lindquist
parents:
203
diff
changeset
|
175 (*fp)(p); // call deallocator |
c4c9b4ac021b
[svn r225] Fixed: delete expressions no longer use llvm's free instruction, which crashes on a GC provided pointer.
lindquist
parents:
203
diff
changeset
|
176 //*p = null; |
132 | 177 return; |
178 } | |
179 } | |
180 else | |
181 { | |
209
c4c9b4ac021b
[svn r225] Fixed: delete expressions no longer use llvm's free instruction, which crashes on a GC provided pointer.
lindquist
parents:
203
diff
changeset
|
182 rt_finalize(cast(void*) p); |
132 | 183 } |
209
c4c9b4ac021b
[svn r225] Fixed: delete expressions no longer use llvm's free instruction, which crashes on a GC provided pointer.
lindquist
parents:
203
diff
changeset
|
184 gc_free(cast(void*) p); |
c4c9b4ac021b
[svn r225] Fixed: delete expressions no longer use llvm's free instruction, which crashes on a GC provided pointer.
lindquist
parents:
203
diff
changeset
|
185 //*p = null; |
132 | 186 } |
187 } | |
188 | |
209
c4c9b4ac021b
[svn r225] Fixed: delete expressions no longer use llvm's free instruction, which crashes on a GC provided pointer.
lindquist
parents:
203
diff
changeset
|
189 /+ |
c4c9b4ac021b
[svn r225] Fixed: delete expressions no longer use llvm's free instruction, which crashes on a GC provided pointer.
lindquist
parents:
203
diff
changeset
|
190 |
132 | 191 /** |
192 * | |
193 */ | |
194 struct Array | |
195 { | |
196 size_t length; | |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
197 void* data; |
132 | 198 } |
199 | |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
200 +/ |
132 | 201 |
202 /** | |
203 * Allocate a new array of length elements. | |
204 * ti is the type of the resulting array, or pointer to element. | |
205 * (For when the array is initialized to 0) | |
206 */ | |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
207 extern (C) void* _d_newarrayT(TypeInfo ti, size_t length) |
132 | 208 { |
209 void* p; | |
210 auto size = ti.next.tsize(); // array element size | |
211 | |
212
4c2689d57ba4
[svn r228] Fixed: when new'ing basic types, the storage was not default initialized.
lindquist
parents:
211
diff
changeset
|
212 debug(PRINTF) printf("_d_newarrayT(length = %u, size = %d)\n", length, size); |
132 | 213 if (length == 0 || size == 0) |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
214 return null; |
132 | 215 |
237
a168a2c3ea48
[svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents:
212
diff
changeset
|
216 version (Asm86) |
132 | 217 { |
218 asm | |
219 { | |
220 mov EAX,size ; | |
221 mul EAX,length ; | |
222 mov size,EAX ; | |
223 jc Loverflow ; | |
224 } | |
225 } | |
226 else | |
227 size *= length; | |
228 p = gc_malloc(size + 1, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0); | |
229 debug(PRINTF) printf(" p = %p\n", p); | |
230 memset(p, 0, size); | |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
231 return p; |
132 | 232 |
233 Loverflow: | |
234 onOutOfMemoryError(); | |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
235 return null; |
132 | 236 } |
237 | |
238 /** | |
239 * For when the array has a non-zero initializer. | |
240 */ | |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
241 extern (C) void* _d_newarrayiT(TypeInfo ti, size_t length) |
132 | 242 { |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
243 void* result; |
132 | 244 auto size = ti.next.tsize(); // array element size |
245 | |
246 debug(PRINTF) printf("_d_newarrayiT(length = %d, size = %d)\n", length, size); | |
247 | |
248 if (length == 0 || size == 0) | |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
249 result = null; |
132 | 250 else |
251 { | |
252 auto initializer = ti.next.init(); | |
253 auto isize = initializer.length; | |
254 auto q = initializer.ptr; | |
237
a168a2c3ea48
[svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents:
212
diff
changeset
|
255 version (Asm86) |
132 | 256 { |
257 asm | |
258 { | |
259 mov EAX,size ; | |
260 mul EAX,length ; | |
261 mov size,EAX ; | |
262 jc Loverflow ; | |
263 } | |
264 } | |
265 else | |
266 size *= length; | |
267 auto p = gc_malloc(size + 1, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0); | |
268 debug(PRINTF) printf(" p = %p\n", p); | |
269 if (isize == 1) | |
270 memset(p, *cast(ubyte*)q, size); | |
271 else if (isize == int.sizeof) | |
272 { | |
273 int init = *cast(int*)q; | |
274 size /= int.sizeof; | |
275 for (size_t u = 0; u < size; u++) | |
276 { | |
277 (cast(int*)p)[u] = init; | |
278 } | |
279 } | |
280 else | |
281 { | |
282 for (size_t u = 0; u < size; u += isize) | |
283 { | |
284 memcpy(p + u, q, isize); | |
285 } | |
286 } | |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
287 result = p; |
132 | 288 } |
289 return result; | |
290 | |
291 Loverflow: | |
292 onOutOfMemoryError(); | |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
293 return null; |
132 | 294 } |
295 | |
296 /** | |
297 * | |
298 */ | |
286
a3b7c19c866c
[svn r307] Fixed: multidimensional new expressions now work. Eg.:
lindquist
parents:
268
diff
changeset
|
299 extern (C) void* _d_newarraymT(TypeInfo ti, int ndims, size_t* dims) |
132 | 300 { |
286
a3b7c19c866c
[svn r307] Fixed: multidimensional new expressions now work. Eg.:
lindquist
parents:
268
diff
changeset
|
301 void* result; |
132 | 302 |
303 debug(PRINTF) printf("_d_newarraymT(ndims = %d)\n", ndims); | |
304 if (ndims == 0) | |
286
a3b7c19c866c
[svn r307] Fixed: multidimensional new expressions now work. Eg.:
lindquist
parents:
268
diff
changeset
|
305 result = null; |
132 | 306 else |
286
a3b7c19c866c
[svn r307] Fixed: multidimensional new expressions now work. Eg.:
lindquist
parents:
268
diff
changeset
|
307 { |
a3b7c19c866c
[svn r307] Fixed: multidimensional new expressions now work. Eg.:
lindquist
parents:
268
diff
changeset
|
308 static void[] foo(TypeInfo ti, size_t* pdim, int ndims) |
132 | 309 { |
310 size_t dim = *pdim; | |
311 void[] p; | |
312 | |
313 debug(PRINTF) printf("foo(ti = %p, ti.next = %p, dim = %d, ndims = %d\n", ti, ti.next, dim, ndims); | |
314 if (ndims == 1) | |
315 { | |
286
a3b7c19c866c
[svn r307] Fixed: multidimensional new expressions now work. Eg.:
lindquist
parents:
268
diff
changeset
|
316 auto r = _d_newarrayT(ti, dim); |
a3b7c19c866c
[svn r307] Fixed: multidimensional new expressions now work. Eg.:
lindquist
parents:
268
diff
changeset
|
317 return r[0 .. dim]; |
132 | 318 } |
319 else | |
320 { | |
321 p = gc_malloc(dim * (void[]).sizeof + 1)[0 .. dim]; | |
322 for (int i = 0; i < dim; i++) | |
323 { | |
324 (cast(void[]*)p.ptr)[i] = foo(ti.next, pdim + 1, ndims - 1); | |
325 } | |
326 } | |
327 return p; | |
328 } | |
329 | |
286
a3b7c19c866c
[svn r307] Fixed: multidimensional new expressions now work. Eg.:
lindquist
parents:
268
diff
changeset
|
330 result = foo(ti, dims, ndims).ptr; |
a3b7c19c866c
[svn r307] Fixed: multidimensional new expressions now work. Eg.:
lindquist
parents:
268
diff
changeset
|
331 debug(PRINTF) printf("result = %p\n", result); |
132 | 332 |
333 version (none) | |
334 { | |
335 for (int i = 0; i < ndims; i++) | |
336 { | |
286
a3b7c19c866c
[svn r307] Fixed: multidimensional new expressions now work. Eg.:
lindquist
parents:
268
diff
changeset
|
337 printf("index %d: %d\n", i, *dims++); |
132 | 338 } |
339 } | |
340 } | |
341 return result; | |
342 } | |
343 | |
344 | |
345 /** | |
346 * | |
347 */ | |
286
a3b7c19c866c
[svn r307] Fixed: multidimensional new expressions now work. Eg.:
lindquist
parents:
268
diff
changeset
|
348 extern (C) void* _d_newarraymiT(TypeInfo ti, int ndims, size_t* dims) |
132 | 349 { |
286
a3b7c19c866c
[svn r307] Fixed: multidimensional new expressions now work. Eg.:
lindquist
parents:
268
diff
changeset
|
350 void* result; |
132 | 351 |
352 debug(PRINTF) printf("_d_newarraymiT(ndims = %d)\n", ndims); | |
353 if (ndims == 0) | |
286
a3b7c19c866c
[svn r307] Fixed: multidimensional new expressions now work. Eg.:
lindquist
parents:
268
diff
changeset
|
354 result = null; |
132 | 355 else |
356 { | |
286
a3b7c19c866c
[svn r307] Fixed: multidimensional new expressions now work. Eg.:
lindquist
parents:
268
diff
changeset
|
357 static void[] foo(TypeInfo ti, size_t* pdim, int ndims) |
132 | 358 { |
359 size_t dim = *pdim; | |
360 void[] p; | |
361 | |
362 if (ndims == 1) | |
363 { | |
364 auto r = _d_newarrayiT(ti, dim); | |
286
a3b7c19c866c
[svn r307] Fixed: multidimensional new expressions now work. Eg.:
lindquist
parents:
268
diff
changeset
|
365 p = r[0 .. dim]; |
132 | 366 } |
367 else | |
368 { | |
369 p = gc_malloc(dim * (void[]).sizeof + 1)[0 .. dim]; | |
370 for (int i = 0; i < dim; i++) | |
371 { | |
372 (cast(void[]*)p.ptr)[i] = foo(ti.next, pdim + 1, ndims - 1); | |
373 } | |
374 } | |
375 return p; | |
376 } | |
377 | |
286
a3b7c19c866c
[svn r307] Fixed: multidimensional new expressions now work. Eg.:
lindquist
parents:
268
diff
changeset
|
378 result = foo(ti, dims, ndims).ptr; |
a3b7c19c866c
[svn r307] Fixed: multidimensional new expressions now work. Eg.:
lindquist
parents:
268
diff
changeset
|
379 debug(PRINTF) printf("result = %p\n", result); |
132 | 380 |
381 version (none) | |
382 { | |
383 for (int i = 0; i < ndims; i++) | |
384 { | |
286
a3b7c19c866c
[svn r307] Fixed: multidimensional new expressions now work. Eg.:
lindquist
parents:
268
diff
changeset
|
385 printf("index %d: %d\n", i, *dims++); |
a3b7c19c866c
[svn r307] Fixed: multidimensional new expressions now work. Eg.:
lindquist
parents:
268
diff
changeset
|
386 printf("init = %d\n", *dims++); |
132 | 387 } |
388 } | |
389 } | |
390 return result; | |
391 } | |
392 | |
286
a3b7c19c866c
[svn r307] Fixed: multidimensional new expressions now work. Eg.:
lindquist
parents:
268
diff
changeset
|
393 /+ |
a3b7c19c866c
[svn r307] Fixed: multidimensional new expressions now work. Eg.:
lindquist
parents:
268
diff
changeset
|
394 |
132 | 395 /** |
396 * | |
397 */ | |
398 void* _d_allocmemory(size_t nbytes) | |
399 { | |
400 return gc_malloc(nbytes); | |
401 } | |
402 | |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
403 +/ |
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
404 |
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
405 /** |
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
406 * for allocating a single POD value |
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
407 */ |
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
408 extern (C) void* _d_allocmemoryT(TypeInfo ti) |
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
409 { |
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
410 return gc_malloc(ti.tsize(), (ti.flags() & 1) ? BlkAttr.NO_SCAN : 0); |
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
411 } |
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
412 |
209
c4c9b4ac021b
[svn r225] Fixed: delete expressions no longer use llvm's free instruction, which crashes on a GC provided pointer.
lindquist
parents:
203
diff
changeset
|
413 /** |
c4c9b4ac021b
[svn r225] Fixed: delete expressions no longer use llvm's free instruction, which crashes on a GC provided pointer.
lindquist
parents:
203
diff
changeset
|
414 * |
c4c9b4ac021b
[svn r225] Fixed: delete expressions no longer use llvm's free instruction, which crashes on a GC provided pointer.
lindquist
parents:
203
diff
changeset
|
415 */ |
c4c9b4ac021b
[svn r225] Fixed: delete expressions no longer use llvm's free instruction, which crashes on a GC provided pointer.
lindquist
parents:
203
diff
changeset
|
416 extern (C) void _d_delarray(size_t plength, void* pdata) |
c4c9b4ac021b
[svn r225] Fixed: delete expressions no longer use llvm's free instruction, which crashes on a GC provided pointer.
lindquist
parents:
203
diff
changeset
|
417 { |
c4c9b4ac021b
[svn r225] Fixed: delete expressions no longer use llvm's free instruction, which crashes on a GC provided pointer.
lindquist
parents:
203
diff
changeset
|
418 // if (p) |
c4c9b4ac021b
[svn r225] Fixed: delete expressions no longer use llvm's free instruction, which crashes on a GC provided pointer.
lindquist
parents:
203
diff
changeset
|
419 // { |
c4c9b4ac021b
[svn r225] Fixed: delete expressions no longer use llvm's free instruction, which crashes on a GC provided pointer.
lindquist
parents:
203
diff
changeset
|
420 assert(!plength || pdata); |
c4c9b4ac021b
[svn r225] Fixed: delete expressions no longer use llvm's free instruction, which crashes on a GC provided pointer.
lindquist
parents:
203
diff
changeset
|
421 |
c4c9b4ac021b
[svn r225] Fixed: delete expressions no longer use llvm's free instruction, which crashes on a GC provided pointer.
lindquist
parents:
203
diff
changeset
|
422 if (pdata) |
c4c9b4ac021b
[svn r225] Fixed: delete expressions no longer use llvm's free instruction, which crashes on a GC provided pointer.
lindquist
parents:
203
diff
changeset
|
423 gc_free(pdata); |
c4c9b4ac021b
[svn r225] Fixed: delete expressions no longer use llvm's free instruction, which crashes on a GC provided pointer.
lindquist
parents:
203
diff
changeset
|
424 // p.data = null; |
c4c9b4ac021b
[svn r225] Fixed: delete expressions no longer use llvm's free instruction, which crashes on a GC provided pointer.
lindquist
parents:
203
diff
changeset
|
425 // p.length = 0; |
c4c9b4ac021b
[svn r225] Fixed: delete expressions no longer use llvm's free instruction, which crashes on a GC provided pointer.
lindquist
parents:
203
diff
changeset
|
426 // } |
c4c9b4ac021b
[svn r225] Fixed: delete expressions no longer use llvm's free instruction, which crashes on a GC provided pointer.
lindquist
parents:
203
diff
changeset
|
427 } |
132 | 428 |
429 /** | |
430 * | |
431 */ | |
209
c4c9b4ac021b
[svn r225] Fixed: delete expressions no longer use llvm's free instruction, which crashes on a GC provided pointer.
lindquist
parents:
203
diff
changeset
|
432 extern (C) void _d_delmemory(void* p) |
132 | 433 { |
434 if (p) | |
435 { | |
209
c4c9b4ac021b
[svn r225] Fixed: delete expressions no longer use llvm's free instruction, which crashes on a GC provided pointer.
lindquist
parents:
203
diff
changeset
|
436 gc_free(p); |
c4c9b4ac021b
[svn r225] Fixed: delete expressions no longer use llvm's free instruction, which crashes on a GC provided pointer.
lindquist
parents:
203
diff
changeset
|
437 //*p = null; |
132 | 438 } |
439 } | |
440 | |
441 | |
442 /** | |
443 * | |
444 */ | |
445 extern (C) void _d_callfinalizer(void* p) | |
446 { | |
447 rt_finalize( p ); | |
448 } | |
449 | |
450 | |
451 /** | |
452 * | |
453 */ | |
454 extern (C) void rt_finalize(void* p, bool det = true) | |
455 { | |
456 debug(PRINTF) printf("rt_finalize(p = %p)\n", p); | |
457 | |
458 if (p) // not necessary if called from gc | |
459 { | |
460 ClassInfo** pc = cast(ClassInfo**)p; | |
461 | |
462 if (*pc) | |
463 { | |
464 ClassInfo c = **pc; | |
465 | |
466 try | |
467 { | |
468 if (det || onCollectResource(cast(Object)p)) | |
469 { | |
470 do | |
471 { | |
472 if (c.destructor) | |
473 { | |
268
23d0d9855cad
[svn r289] Fixed: right shift >> was broken for unsigned types.
lindquist
parents:
237
diff
changeset
|
474 debug(PRINTF) printf("calling dtor of %.*s\n", c.name.length, c.name.ptr); |
132 | 475 fp_t fp = cast(fp_t)c.destructor; |
476 (*fp)(cast(Object)p); // call destructor | |
477 } | |
478 c = c.base; | |
479 } while (c); | |
480 } | |
481 if ((cast(void**)p)[1]) // if monitor is not null | |
482 _d_monitordelete(cast(Object)p, det); | |
483 } | |
484 catch (Exception e) | |
485 { | |
486 onFinalizeError(**pc, e); | |
487 } | |
488 finally | |
489 { | |
490 *pc = null; // zero vptr | |
491 } | |
492 } | |
493 } | |
494 } | |
495 | |
496 /** | |
497 * Resize dynamic arrays with 0 initializers. | |
498 */ | |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
499 extern (C) byte* _d_arraysetlengthT(TypeInfo ti, size_t newlength, size_t plength, byte* pdata) |
132 | 500 in |
501 { | |
502 assert(ti); | |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
503 assert(!plength || pdata); |
132 | 504 } |
505 body | |
506 { | |
507 byte* newdata; | |
508 size_t sizeelem = ti.next.tsize(); | |
509 | |
510 debug(PRINTF) | |
511 { | |
211
f66219e0d530
[svn r227] Fixed: crash in lifetime.d when resizing array of AAs by .length assignment.
lindquist
parents:
209
diff
changeset
|
512 printf("_d_arraysetlengthT(sizeelem = %d, newlength = %d)\n", sizeelem, newlength); |
f66219e0d530
[svn r227] Fixed: crash in lifetime.d when resizing array of AAs by .length assignment.
lindquist
parents:
209
diff
changeset
|
513 printf("\tp.data = %p, p.length = %d\n", pdata, plength); |
132 | 514 } |
515 | |
516 if (newlength) | |
517 { | |
237
a168a2c3ea48
[svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents:
212
diff
changeset
|
518 version (Asm86) |
132 | 519 { |
520 size_t newsize = void; | |
521 | |
522 asm | |
523 { | |
524 mov EAX, newlength; | |
525 mul EAX, sizeelem; | |
526 mov newsize, EAX; | |
527 jc Loverflow; | |
528 } | |
529 } | |
530 else | |
531 { | |
532 size_t newsize = sizeelem * newlength; | |
533 | |
534 if (newsize / newlength != sizeelem) | |
535 goto Loverflow; | |
536 } | |
537 | |
538 debug(PRINTF) printf("newsize = %x, newlength = %x\n", newsize, newlength); | |
539 | |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
540 if (pdata) |
132 | 541 { |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
542 newdata = pdata; |
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
543 if (newlength > plength) |
132 | 544 { |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
545 size_t size = plength * sizeelem; |
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
546 auto info = gc_query(pdata); |
132 | 547 |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
548 if (info.size <= newsize || info.base != pdata) |
132 | 549 { |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
550 if (info.size >= PAGESIZE && info.base == pdata) |
132 | 551 { // Try to extend in-place |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
552 auto u = gc_extend(pdata, (newsize + 1) - info.size, (newsize + 1) - info.size); |
132 | 553 if (u) |
554 { | |
555 goto L1; | |
556 } | |
557 } | |
558 newdata = cast(byte *)gc_malloc(newsize + 1, info.attr); | |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
559 newdata[0 .. size] = pdata[0 .. size]; |
132 | 560 } |
561 L1: | |
562 newdata[size .. newsize] = 0; | |
563 } | |
564 } | |
565 else | |
566 { | |
567 newdata = cast(byte *)gc_calloc(newsize + 1, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0); | |
568 } | |
569 } | |
570 else | |
571 { | |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
572 newdata = pdata; |
132 | 573 } |
574 | |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
575 return newdata; |
132 | 576 |
577 Loverflow: | |
578 onOutOfMemoryError(); | |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
579 return null; |
132 | 580 } |
581 | |
582 | |
583 /** | |
584 * Resize arrays for non-zero initializers. | |
585 * p pointer to array lvalue to be updated | |
586 * newlength new .length property of array | |
587 * sizeelem size of each element of array | |
588 * initsize size of initializer | |
589 * ... initializer | |
590 */ | |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
591 extern (C) byte* _d_arraysetlengthiT(TypeInfo ti, size_t newlength, size_t plength, byte* pdata) |
132 | 592 in |
593 { | |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
594 assert(!plength || pdata); |
132 | 595 } |
596 body | |
597 { | |
598 byte* newdata; | |
211
f66219e0d530
[svn r227] Fixed: crash in lifetime.d when resizing array of AAs by .length assignment.
lindquist
parents:
209
diff
changeset
|
599 TypeInfo tinext = ti.next; |
f66219e0d530
[svn r227] Fixed: crash in lifetime.d when resizing array of AAs by .length assignment.
lindquist
parents:
209
diff
changeset
|
600 size_t sizeelem = tinext.tsize(); |
f66219e0d530
[svn r227] Fixed: crash in lifetime.d when resizing array of AAs by .length assignment.
lindquist
parents:
209
diff
changeset
|
601 void[] initializer = tinext.init(); |
132 | 602 size_t initsize = initializer.length; |
603 | |
604 assert(sizeelem); | |
605 assert(initsize); | |
606 assert(initsize <= sizeelem); | |
607 assert((sizeelem / initsize) * initsize == sizeelem); | |
608 | |
609 debug(PRINTF) | |
610 { | |
211
f66219e0d530
[svn r227] Fixed: crash in lifetime.d when resizing array of AAs by .length assignment.
lindquist
parents:
209
diff
changeset
|
611 printf("_d_arraysetlengthiT(sizeelem = %d, newlength = %d, initsize = %d)\n", sizeelem, newlength, initsize); |
f66219e0d530
[svn r227] Fixed: crash in lifetime.d when resizing array of AAs by .length assignment.
lindquist
parents:
209
diff
changeset
|
612 printf("\tp.data = %p, p.length = %d\n", pdata, plength); |
132 | 613 } |
614 | |
615 if (newlength) | |
616 { | |
237
a168a2c3ea48
[svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents:
212
diff
changeset
|
617 version (Asm86) |
132 | 618 { |
619 size_t newsize = void; | |
620 | |
621 asm | |
622 { | |
623 mov EAX,newlength ; | |
624 mul EAX,sizeelem ; | |
625 mov newsize,EAX ; | |
626 jc Loverflow ; | |
627 } | |
628 } | |
629 else | |
630 { | |
631 size_t newsize = sizeelem * newlength; | |
632 | |
633 if (newsize / newlength != sizeelem) | |
634 goto Loverflow; | |
635 } | |
636 debug(PRINTF) printf("newsize = %x, newlength = %x\n", newsize, newlength); | |
637 | |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
638 size_t size = plength * sizeelem; |
132 | 639 |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
640 if (pdata) |
132 | 641 { |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
642 newdata = pdata; |
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
643 if (newlength > plength) |
132 | 644 { |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
645 auto info = gc_query(pdata); |
132 | 646 |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
647 if (info.size <= newsize || info.base != pdata) |
132 | 648 { |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
649 if (info.size >= PAGESIZE && info.base == pdata) |
132 | 650 { // Try to extend in-place |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
651 auto u = gc_extend(pdata, (newsize + 1) - info.size, (newsize + 1) - info.size); |
132 | 652 if (u) |
653 { | |
654 goto L1; | |
655 } | |
656 } | |
657 newdata = cast(byte *)gc_malloc(newsize + 1, info.attr); | |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
658 newdata[0 .. size] = pdata[0 .. size]; |
132 | 659 L1: ; |
660 } | |
661 } | |
662 } | |
663 else | |
664 { | |
211
f66219e0d530
[svn r227] Fixed: crash in lifetime.d when resizing array of AAs by .length assignment.
lindquist
parents:
209
diff
changeset
|
665 newdata = cast(byte *)gc_malloc(newsize + 1, !(tinext.flags() & 1) ? BlkAttr.NO_SCAN : 0); |
132 | 666 } |
667 | |
668 auto q = initializer.ptr; // pointer to initializer | |
669 | |
670 if (newsize > size) | |
671 { | |
672 if (initsize == 1) | |
673 { | |
674 debug(PRINTF) printf("newdata = %p, size = %d, newsize = %d, *q = %d\n", newdata, size, newsize, *cast(byte*)q); | |
675 newdata[size .. newsize] = *(cast(byte*)q); | |
676 } | |
677 else | |
678 { | |
679 for (size_t u = size; u < newsize; u += initsize) | |
680 { | |
681 memcpy(newdata + u, q, initsize); | |
682 } | |
683 } | |
684 } | |
685 } | |
686 else | |
687 { | |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
688 newdata = pdata; |
132 | 689 } |
690 | |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
691 return newdata; |
132 | 692 |
693 Loverflow: | |
694 onOutOfMemoryError(); | |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
695 return null; |
132 | 696 } |
697 | |
203
e881c9b1c738
[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 .
lindquist
parents:
137
diff
changeset
|
698 /+ |
132 | 699 |
700 /** | |
701 * Append y[] to array x[]. | |
702 * size is size of each array element. | |
703 */ | |
704 extern (C) long _d_arrayappendT(TypeInfo ti, Array *px, byte[] y) | |
705 { | |
706 auto sizeelem = ti.next.tsize(); // array element size | |
707 auto info = gc_query(px.data); | |
708 auto length = px.length; | |
709 auto newlength = length + y.length; | |
710 auto newsize = newlength * sizeelem; | |
711 | |
712 if (info.size < newsize || info.base != px.data) | |
713 { byte* newdata; | |
714 | |
715 if (info.size >= PAGESIZE && info.base == px.data) | |
716 { // Try to extend in-place | |
717 auto u = gc_extend(px.data, (newsize + 1) - info.size, (newsize + 1) - info.size); | |
718 if (u) | |
719 { | |
720 goto L1; | |
721 } | |
722 } | |
723 newdata = cast(byte *)gc_malloc(newCapacity(newlength, sizeelem) + 1, info.attr); | |
724 memcpy(newdata, px.data, length * sizeelem); | |
725 px.data = newdata; | |
726 } | |
727 L1: | |
728 px.length = newlength; | |
729 memcpy(px.data + length * sizeelem, y.ptr, y.length * sizeelem); | |
730 return *cast(long*)px; | |
731 } | |
732 | |
733 | |
734 /** | |
735 * | |
736 */ | |
737 size_t newCapacity(size_t newlength, size_t size) | |
738 { | |
739 version(none) | |
740 { | |
741 size_t newcap = newlength * size; | |
742 } | |
743 else | |
744 { | |
745 /* | |
746 * Better version by Dave Fladebo: | |
747 * This uses an inverse logorithmic algorithm to pre-allocate a bit more | |
748 * space for larger arrays. | |
749 * - Arrays smaller than PAGESIZE bytes are left as-is, so for the most | |
750 * common cases, memory allocation is 1 to 1. The small overhead added | |
751 * doesn't affect small array perf. (it's virtually the same as | |
752 * current). | |
753 * - Larger arrays have some space pre-allocated. | |
754 * - As the arrays grow, the relative pre-allocated space shrinks. | |
755 * - The logorithmic algorithm allocates relatively more space for | |
756 * mid-size arrays, making it very fast for medium arrays (for | |
757 * mid-to-large arrays, this turns out to be quite a bit faster than the | |
758 * equivalent realloc() code in C, on Linux at least. Small arrays are | |
759 * just as fast as GCC). | |
760 * - Perhaps most importantly, overall memory usage and stress on the GC | |
761 * is decreased significantly for demanding environments. | |
762 */ | |
763 size_t newcap = newlength * size; | |
764 size_t newext = 0; | |
765 | |
766 if (newcap > PAGESIZE) | |
767 { | |
768 //double mult2 = 1.0 + (size / log10(pow(newcap * 2.0,2.0))); | |
769 | |
770 // redo above line using only integer math | |
771 | |
772 static int log2plus1(size_t c) | |
773 { int i; | |
774 | |
775 if (c == 0) | |
776 i = -1; | |
777 else | |
778 for (i = 1; c >>= 1; i++) | |
779 { | |
780 } | |
781 return i; | |
782 } | |
783 | |
784 /* The following setting for mult sets how much bigger | |
785 * the new size will be over what is actually needed. | |
786 * 100 means the same size, more means proportionally more. | |
787 * More means faster but more memory consumption. | |
788 */ | |
789 //long mult = 100 + (1000L * size) / (6 * log2plus1(newcap)); | |
790 long mult = 100 + (1000L * size) / log2plus1(newcap); | |
791 | |
792 // testing shows 1.02 for large arrays is about the point of diminishing return | |
793 if (mult < 102) | |
794 mult = 102; | |
795 newext = cast(size_t)((newcap * mult) / 100); | |
796 newext -= newext % size; | |
797 debug(PRINTF) printf("mult: %2.2f, alloc: %2.2f\n",mult/100.0,newext / cast(double)size); | |
798 } | |
799 newcap = newext > newcap ? newext : newcap; | |
800 debug(PRINTF) printf("newcap = %d, newlength = %d, size = %d\n", newcap, newlength, size); | |
801 } | |
802 return newcap; | |
803 } | |
804 | |
805 | |
806 /** | |
807 * | |
808 */ | |
809 extern (C) byte[] _d_arrayappendcT(TypeInfo ti, inout byte[] x, ...) | |
810 { | |
811 auto sizeelem = ti.next.tsize(); // array element size | |
812 auto info = gc_query(x.ptr); | |
813 auto length = x.length; | |
814 auto newlength = length + 1; | |
815 auto newsize = newlength * sizeelem; | |
816 | |
817 assert(info.size == 0 || length * sizeelem <= info.size); | |
818 | |
819 debug(PRINTF) printf("_d_arrayappendcT(sizeelem = %d, ptr = %p, length = %d, cap = %d)\n", sizeelem, x.ptr, x.length, info.size); | |
820 | |
821 if (info.size <= newsize || info.base != x.ptr) | |
822 { byte* newdata; | |
823 | |
824 if (info.size >= PAGESIZE && info.base == x.ptr) | |
825 { // Try to extend in-place | |
826 auto u = gc_extend(x.ptr, (newsize + 1) - info.size, (newsize + 1) - info.size); | |
827 if (u) | |
828 { | |
829 goto L1; | |
830 } | |
831 } | |
832 debug(PRINTF) printf("_d_arrayappendcT(length = %d, newlength = %d, cap = %d)\n", length, newlength, info.size); | |
833 auto newcap = newCapacity(newlength, sizeelem); | |
834 assert(newcap >= newlength * sizeelem); | |
835 newdata = cast(byte *)gc_malloc(newcap + 1, info.attr); | |
836 memcpy(newdata, x.ptr, length * sizeelem); | |
837 (cast(void**)(&x))[1] = newdata; | |
838 } | |
839 L1: | |
840 byte *argp = cast(byte *)(&ti + 2); | |
841 | |
842 *cast(size_t *)&x = newlength; | |
843 x.ptr[length * sizeelem .. newsize] = argp[0 .. sizeelem]; | |
844 assert((cast(size_t)x.ptr & 15) == 0); | |
845 assert(gc_sizeOf(x.ptr) > x.length * sizeelem); | |
846 return x; | |
847 } | |
848 | |
849 | |
850 /** | |
851 * | |
852 */ | |
853 extern (C) byte[] _d_arraycatT(TypeInfo ti, byte[] x, byte[] y) | |
854 out (result) | |
855 { | |
856 auto sizeelem = ti.next.tsize(); // array element size | |
857 debug(PRINTF) printf("_d_arraycatT(%d,%p ~ %d,%p sizeelem = %d => %d,%p)\n", x.length, x.ptr, y.length, y.ptr, sizeelem, result.length, result.ptr); | |
858 assert(result.length == x.length + y.length); | |
859 for (size_t i = 0; i < x.length * sizeelem; i++) | |
860 assert((cast(byte*)result)[i] == (cast(byte*)x)[i]); | |
861 for (size_t i = 0; i < y.length * sizeelem; i++) | |
862 assert((cast(byte*)result)[x.length * sizeelem + i] == (cast(byte*)y)[i]); | |
863 | |
864 size_t cap = gc_sizeOf(result.ptr); | |
865 assert(!cap || cap > result.length * sizeelem); | |
866 } | |
867 body | |
868 { | |
869 version (none) | |
870 { | |
871 /* Cannot use this optimization because: | |
872 * char[] a, b; | |
873 * char c = 'a'; | |
874 * b = a ~ c; | |
875 * c = 'b'; | |
876 * will change the contents of b. | |
877 */ | |
878 if (!y.length) | |
879 return x; | |
880 if (!x.length) | |
881 return y; | |
882 } | |
883 | |
884 debug(PRINTF) printf("_d_arraycatT(%d,%p ~ %d,%p)\n", x.length, x.ptr, y.length, y.ptr); | |
885 auto sizeelem = ti.next.tsize(); // array element size | |
886 debug(PRINTF) printf("_d_arraycatT(%d,%p ~ %d,%p sizeelem = %d)\n", x.length, x.ptr, y.length, y.ptr, sizeelem); | |
887 size_t xlen = x.length * sizeelem; | |
888 size_t ylen = y.length * sizeelem; | |
889 size_t len = xlen + ylen; | |
890 | |
891 if (!len) | |
892 return null; | |
893 | |
894 byte* p = cast(byte*)gc_malloc(len + 1, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0); | |
895 memcpy(p, x.ptr, xlen); | |
896 memcpy(p + xlen, y.ptr, ylen); | |
897 p[len] = 0; | |
898 return p[0 .. x.length + y.length]; | |
899 } | |
900 | |
901 | |
902 /** | |
903 * | |
904 */ | |
905 extern (C) byte[] _d_arraycatnT(TypeInfo ti, uint n, ...) | |
906 { void* a; | |
907 size_t length; | |
908 byte[]* p; | |
909 uint i; | |
910 byte[] b; | |
911 auto size = ti.next.tsize(); // array element size | |
912 | |
913 p = cast(byte[]*)(&n + 1); | |
914 | |
915 for (i = 0; i < n; i++) | |
916 { | |
917 b = *p++; | |
918 length += b.length; | |
919 } | |
920 if (!length) | |
921 return null; | |
922 | |
923 a = gc_malloc(length * size, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0); | |
924 p = cast(byte[]*)(&n + 1); | |
925 | |
926 uint j = 0; | |
927 for (i = 0; i < n; i++) | |
928 { | |
929 b = *p++; | |
930 if (b.length) | |
931 { | |
932 memcpy(a + j, b.ptr, b.length * size); | |
933 j += b.length * size; | |
934 } | |
935 } | |
936 | |
937 byte[] result; | |
938 *cast(int *)&result = length; // jam length | |
939 (cast(void **)&result)[1] = a; // jam ptr | |
940 return result; | |
941 } | |
942 | |
943 | |
944 /** | |
945 * | |
946 */ | |
947 extern (C) void* _d_arrayliteralT(TypeInfo ti, size_t length, ...) | |
948 { | |
949 auto sizeelem = ti.next.tsize(); // array element size | |
950 void* result; | |
951 | |
952 debug(PRINTF) printf("_d_arrayliteralT(sizeelem = %d, length = %d)\n", sizeelem, length); | |
953 if (length == 0 || sizeelem == 0) | |
954 result = null; | |
955 else | |
956 { | |
957 result = gc_malloc(length * sizeelem, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0); | |
958 | |
959 va_list q; | |
960 va_start!(size_t)(q, length); | |
961 | |
962 size_t stacksize = (sizeelem + int.sizeof - 1) & ~(int.sizeof - 1); | |
963 | |
964 if (stacksize == sizeelem) | |
965 { | |
966 memcpy(result, q, length * sizeelem); | |
967 } | |
968 else | |
969 { | |
970 for (size_t i = 0; i < length; i++) | |
971 { | |
972 memcpy(result + i * sizeelem, q, sizeelem); | |
973 q += stacksize; | |
974 } | |
975 } | |
976 | |
977 va_end(q); | |
978 } | |
979 return result; | |
980 } | |
981 | |
982 +/ | |
983 | |
984 | |
985 /** | |
986 * Support for array.dup property. | |
987 */ | |
988 struct Array2 | |
989 { | |
990 size_t length; | |
991 void* ptr; | |
992 } | |
993 | |
994 | |
995 /** | |
996 * | |
997 */ | |
998 extern (C) Array2 _adDupT(TypeInfo ti, Array2 a) | |
999 out (result) | |
1000 { | |
1001 auto sizeelem = ti.next.tsize(); // array element size | |
1002 assert(memcmp(result.ptr, a.ptr, a.length * sizeelem) == 0); | |
1003 } | |
1004 body | |
1005 { | |
1006 Array2 r; | |
1007 | |
1008 if (a.length) | |
1009 { | |
1010 auto sizeelem = ti.next.tsize(); // array element size | |
1011 auto size = a.length * sizeelem; | |
1012 r.ptr = gc_malloc(size, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0); | |
1013 r.length = a.length; | |
1014 memcpy(r.ptr, a.ptr, size); | |
1015 } | |
1016 return r; | |
1017 } | |
1018 | |
1019 | |
1020 unittest | |
1021 { | |
1022 int[] a; | |
1023 int[] b; | |
1024 int i; | |
1025 | |
1026 a = new int[3]; | |
1027 a[0] = 1; a[1] = 2; a[2] = 3; | |
1028 b = a.dup; | |
1029 assert(b.length == 3); | |
1030 for (i = 0; i < 3; i++) | |
1031 assert(b[i] == i + 1); | |
1032 } |