Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 1113 lines (969 sloc) 25.311 kb
9c1d230 committing experimental branch content
Laurent Sansonetti authored
1 /*
2 * MacRuby implementation of Ruby 1.9's gc.c.
3 *
4 * This file is covered by the Ruby license. See COPYING for more details.
5 *
9595725 update copyrights to 2011
Laurent Sansonetti authored
6 * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
9c1d230 committing experimental branch content
Laurent Sansonetti authored
7 * Copyright (C) 1993-2007 Yukihiro Matsumoto
8 * Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
9 * Copyright (C) 2000 Information-technology Promotion Agency, Japan
10 */
11
f34416e system auto_zone.h is now includeable
Laurent Sansonetti authored
12 #include "ruby/config.h"
217d02e load config.h before
Laurent Sansonetti authored
13
bb3089e auto_zone.h should not be exported
Laurent Sansonetti authored
14 #if HAVE_AUTO_ZONE_H
15 # include <auto_zone.h>
16 #else
17 # include "auto_zone_1060.h"
18 #endif
19
d0898dd include/ruby/macruby.h -> macruby_internal.h
Laurent Sansonetti authored
20 #include "macruby_internal.h"
9c1d230 committing experimental branch content
Laurent Sansonetti authored
21 #include "ruby/signal.h"
22 #include "ruby/st.h"
23 #include "ruby/node.h"
24 #include "ruby/io.h"
25 #include "ruby/util.h"
26 #include "objc.h"
cb65416 the great schism, part I
Laurent Sansonetti authored
27 #include "vm.h"
639c64d implemented ObjectSpace finalizers (experimental)
Laurent Sansonetti authored
28 #include "id.h"
311a41b rewrote class flags to not use the version field anymore, better typi…
Laurent Sansonetti authored
29 #include "class.h"
9c1d230 committing experimental branch content
Laurent Sansonetti authored
30
31 #ifdef HAVE_SYS_TIME_H
32 #include <sys/time.h>
33 #endif
34
35 #ifdef HAVE_SYS_RESOURCE_H
36 #include <sys/resource.h>
37 #endif
38
39 #include <mach/mach.h>
0cd758f adding a new optimized Array for default allocations plus various opt…
Laurent Sansonetti authored
40
41 auto_zone_t *__auto_zone = NULL;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
42
43 static VALUE nomem_error;
44
45 static bool dont_gc = false;
46
47 void
48 rb_memerror(void)
49 {
50 rb_exc_raise(nomem_error);
51 }
52
53 /*
54 * call-seq:
55 * GC.stress => true or false
56 *
57 * returns current status of GC stress mode.
58 */
59
292c513 register not implemented methods with rb_f_notimplement()
Laurent Sansonetti authored
60 #if 0
9c1d230 committing experimental branch content
Laurent Sansonetti authored
61 static VALUE
62 gc_stress_get(VALUE self, SEL sel)
63 {
64 return Qnil;
65 }
292c513 register not implemented methods with rb_f_notimplement()
Laurent Sansonetti authored
66 #else
67 # define gc_stress_get rb_f_notimplement
68 #endif
9c1d230 committing experimental branch content
Laurent Sansonetti authored
69
70 /*
71 * call-seq:
72 * GC.stress = bool => bool
73 *
74 * updates GC stress mode.
75 *
76 * When GC.stress = true, GC is invoked for all GC opportunity:
77 * all memory and object allocation.
78 *
79 * Since it makes Ruby very slow, it is only for debugging.
80 */
81
292c513 register not implemented methods with rb_f_notimplement()
Laurent Sansonetti authored
82 #if 0
9c1d230 committing experimental branch content
Laurent Sansonetti authored
83 static VALUE
84 gc_stress_set(VALUE self, SEL sel, VALUE flag)
85 {
86 return Qnil;
87 }
292c513 register not implemented methods with rb_f_notimplement()
Laurent Sansonetti authored
88 #else
89 # define gc_stress_set rb_f_notimplement
90 #endif
9c1d230 committing experimental branch content
Laurent Sansonetti authored
91
92 static int garbage_collect(void);
93
94 static void
95 rb_objc_no_gc_error(void)
96 {
97 fprintf(stderr,
98 "The client that links against MacRuby was not built for "\
99 "GC. Please turn on garbage collection (-fobjc-gc) and "\
100 "try again.\n");
101 exit(1);
102 }
103
8511bcb added xmalloc_ptrs() function and use it when it's necessary
Laurent Sansonetti authored
104 static inline void *
105 ruby_xmalloc_memory(size_t size, int type)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
106 {
071e98c xmalloc must be called with a size > 0
Laurent Sansonetti authored
107 assert(size > 0);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
108 if (__auto_zone == NULL) {
109 rb_objc_no_gc_error();
110 }
111
8511bcb added xmalloc_ptrs() function and use it when it's necessary
Laurent Sansonetti authored
112 void *mem = auto_zone_allocate_object(__auto_zone, size, type, 0, 0);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
113 if (mem == NULL) {
114 rb_memerror();
115 }
116 return mem;
117 }
118
119 void *
8511bcb added xmalloc_ptrs() function and use it when it's necessary
Laurent Sansonetti authored
120 ruby_xmalloc(size_t size)
121 {
122 return ruby_xmalloc_memory(size, AUTO_MEMORY_SCANNED);
123 }
124
125 void *
126 ruby_xmalloc_ptrs(size_t size)
127 {
128 int type;
94d1a09 @Watson1978 fix the build error on Lion
Watson1978 authored
129 //#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
130 //#define AUTO_POINTERS_ONLY (1 << 2)
131 //#define AUTO_MEMORY_ALL_POINTERS AUTO_POINTERS_ONLY
132 //
133 // type = AUTO_MEMORY_ALL_POINTERS;
134 //#else
8511bcb added xmalloc_ptrs() function and use it when it's necessary
Laurent Sansonetti authored
135 type = AUTO_MEMORY_SCANNED;
94d1a09 @Watson1978 fix the build error on Lion
Watson1978 authored
136 //#endif
8511bcb added xmalloc_ptrs() function and use it when it's necessary
Laurent Sansonetti authored
137 return ruby_xmalloc_memory(size, type);
138 }
139
140 void *
9c1d230 committing experimental branch content
Laurent Sansonetti authored
141 ruby_xmalloc2(size_t n, size_t size)
142 {
143 size_t len = size * n;
144 if (n != 0 && size != len / n) {
145 rb_raise(rb_eArgError, "malloc: possible integer overflow");
146 }
147 return ruby_xmalloc(len);
148 }
149
150 void *
151 ruby_xcalloc(size_t n, size_t size)
152 {
8511bcb added xmalloc_ptrs() function and use it when it's necessary
Laurent Sansonetti authored
153 void *mem = ruby_xmalloc2(n, size);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
154 memset(mem, 0, n * size);
155 return mem;
156 }
157
158 void *
159 ruby_xrealloc(void *ptr, size_t size)
160 {
161 if (ptr == NULL) {
162 return ruby_xmalloc(size);
163 }
164 if (size == 0) {
165 size = 1;
166 }
8511bcb added xmalloc_ptrs() function and use it when it's necessary
Laurent Sansonetti authored
167 void *mem = malloc_zone_realloc(__auto_zone, ptr, size);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
168 if (mem == NULL) {
169 rb_memerror();
170 }
171 return mem;
172 }
173
174 void *
175 ruby_xrealloc2(void *ptr, size_t n, size_t size)
176 {
177 size_t len = size * n;
178 if (n != 0 && size != len / n) {
179 rb_raise(rb_eArgError, "realloc: possible integer overflow");
180 }
181 return ruby_xrealloc(ptr, len);
182 }
183
184 void
185 ruby_xfree(void *ptr)
186 {
187 if (ptr != NULL) {
188 auto_zone_retain(__auto_zone, ptr);
189 malloc_zone_free(__auto_zone, ptr);
190 }
191 }
192
193 /*
194 * call-seq:
195 * GC.enable => true or false
196 *
197 * Enables garbage collection, returning <code>true</code> if garbage
198 * collection was previously disabled.
199 *
200 * GC.disable #=> false
201 * GC.enable #=> true
202 * GC.enable #=> false
203 *
204 */
205
206 VALUE
207 rb_gc_enable(VALUE self, SEL sel)
208 {
209 int old = dont_gc;
210
211 auto_collector_reenable(__auto_zone);
212 dont_gc = Qfalse;
bdf345a Improve core/gc pass rate
Thibault Martin-Lagardette authored
213 return old ? Qtrue : Qfalse;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
214 }
215
216 /*
217 * call-seq:
218 * GC.disable => true or false
219 *
220 * Disables garbage collection, returning <code>true</code> if garbage
221 * collection was already disabled.
222 *
223 * GC.disable #=> false
224 * GC.disable #=> true
225 *
226 */
227
228 VALUE
229 rb_gc_disable(VALUE self, SEL sel)
230 {
231 int old = dont_gc;
232
233 auto_collector_disable(__auto_zone);
234 dont_gc = Qtrue;
bdf345a Improve core/gc pass rate
Thibault Martin-Lagardette authored
235 return old ? Qtrue : Qfalse;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
236 }
237
238 VALUE rb_mGC;
239
240 void *
241 rb_gc_memmove(void *dst, const void *src, size_t len)
242 {
243 return auto_zone_write_barrier_memmove(__auto_zone, dst, src, len);
244 }
245
246 void
0cd758f adding a new optimized Array for default allocations plus various opt…
Laurent Sansonetti authored
247 rb_objc_set_associative_ref(void *obj, void *key, void *val)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
248 {
0cd758f adding a new optimized Array for default allocations plus various opt…
Laurent Sansonetti authored
249 auto_zone_set_associative_ref(__auto_zone, obj, key, val);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
250 }
251
0cd758f adding a new optimized Array for default allocations plus various opt…
Laurent Sansonetti authored
252 void *
253 rb_objc_get_associative_ref(void *obj, void *key)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
254 {
0cd758f adding a new optimized Array for default allocations plus various opt…
Laurent Sansonetti authored
255 return auto_zone_get_associative_ref(__auto_zone, obj, key);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
256 }
257
d44f1d6 fixed GC problems in oniguruma: make sure st.c tables are retained/re…
Laurent Sansonetti authored
258 const void *
0cd758f adding a new optimized Array for default allocations plus various opt…
Laurent Sansonetti authored
259 rb_objc_retain_ni(const void *addr)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
260 {
4b7c757 cleaning a bit public headers, added support for methods defined for …
Laurent Sansonetti authored
261 return rb_objc_retain((void *)addr);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
262 }
263
0cd758f adding a new optimized Array for default allocations plus various opt…
Laurent Sansonetti authored
264 const void *
265 rb_objc_release_ni(const void *addr)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
266 {
4b7c757 cleaning a bit public headers, added support for methods defined for …
Laurent Sansonetti authored
267 return rb_objc_release((void *)addr);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
268 }
269
270 void
271 rb_register_mark_object(VALUE obj)
272 {
6027d5e Use `GC_RETAIN` instead of `rb_gc_register_address` in `rb_register_m…
Thibault Martin-Lagardette authored
273 GC_RETAIN(obj);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
274 }
275
276 void
277 rb_gc_unregister_address(VALUE *addr)
278 {
279 /* TODO: implement me */
280 }
281
282 static void *__nsobject = NULL;
283
284 void *
285 rb_objc_newobj(size_t size)
286 {
287 void *obj;
288
2615970 fixed a few bugs in ObjectSpace#each_object
Laurent Sansonetti authored
289 obj = auto_zone_allocate_object(__auto_zone, size, AUTO_OBJECT_SCANNED,
290 0, 0);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
291 assert(obj != NULL);
292 RBASIC(obj)->klass = (VALUE)__nsobject;
293 return obj;
294 }
295
296 void
297 rb_objc_gc_register_thread(void)
298 {
299 auto_zone_register_thread(__auto_zone);
300 }
301
302 void
303 rb_objc_gc_unregister_thread(void)
304 {
305 auto_zone_unregister_thread(__auto_zone);
306 }
307
308 NODE*
309 rb_node_newnode(enum node_type type, VALUE a0, VALUE a1, VALUE a2)
310 {
311 NODE *n = xmalloc(sizeof(struct RNode));
312
313 n->flags |= T_NODE;
314 nd_set_type(n, type);
315
316 GC_WB(&n->u1.value, a0);
317 GC_WB(&n->u2.value, a1);
318 GC_WB(&n->u3.value, a2);
319
2f9d8df revert r2883
Laurent Sansonetti authored
320 // FIXME this retain is added because the parser is NOT GC-safe at this point
321 GC_RETAIN(n);
322
9c1d230 committing experimental branch content
Laurent Sansonetti authored
323 return n;
324 }
325
046466e unrelease parser nodes post execution
Laurent Sansonetti authored
326 const char *ruby_node_name(int node);
327
328 void
329 rb_node_release(NODE *node)
330 {
331 if (node == NULL || node == (NODE *)-1) {
332 return;
333 }
334
335 // static int c = 0;
336 // printf("%d RELEASE %s %p\n", ++c, ruby_node_name(nd_type(node)), node);
337
338 switch (nd_type(node)) {
339 case NODE_IF: /* 1,2,3 */
340 case NODE_FOR:
341 case NODE_ITER:
342 case NODE_WHEN:
343 case NODE_MASGN:
344 case NODE_RESCUE:
345 case NODE_RESBODY:
346 case NODE_CLASS:
347 case NODE_BLOCK_PASS:
348 rb_node_release(node->u2.node);
349 /* fall through */
350 case NODE_BLOCK: /* 1,3 */
351 case NODE_OPTBLOCK:
352 case NODE_ARRAY:
353 case NODE_ENSURE:
354 case NODE_CALL:
355 case NODE_DEFS:
356 case NODE_OP_ASGN1:
357 case NODE_ARGS:
358 rb_node_release(node->u1.node);
359 /* fall through */
360 case NODE_SUPER: /* 3 */
361 case NODE_FCALL:
362 case NODE_DEFN:
363 case NODE_ARGS_AUX:
364 rb_node_release(node->u3.node);
365 break;
366
e138211 do not try to release NODE_METHOD nodes
Laurent Sansonetti authored
367 case NODE_WHILE: /* 1,2 */
046466e unrelease parser nodes post execution
Laurent Sansonetti authored
368 case NODE_UNTIL:
369 case NODE_AND:
370 case NODE_OR:
371 case NODE_CASE:
372 case NODE_SCLASS:
373 case NODE_DOT2:
374 case NODE_DOT3:
375 case NODE_FLIP2:
376 case NODE_FLIP3:
377 case NODE_MATCH2:
378 case NODE_MATCH3:
379 case NODE_OP_ASGN_OR:
380 case NODE_OP_ASGN_AND:
381 case NODE_MODULE:
382 case NODE_ARGSCAT:
383 rb_node_release(node->u1.node);
384 /* fall through */
385 case NODE_FBODY: /* 2 */
386 case NODE_GASGN:
387 case NODE_LASGN:
388 case NODE_DASGN:
389 case NODE_DASGN_CURR:
390 case NODE_IASGN:
391 case NODE_IASGN2:
392 case NODE_CVASGN:
393 case NODE_OPT_N:
394 case NODE_EVSTR:
395 case NODE_UNDEF:
396 case NODE_POSTEXE:
397 rb_node_release(node->u2.node);
398 break;
399
400 case NODE_HASH: /* 1 */
401 case NODE_DEFINED:
402 case NODE_RETURN:
403 case NODE_BREAK:
404 case NODE_NEXT:
405 case NODE_YIELD:
406 case NODE_COLON2:
407 case NODE_SPLAT:
408 case NODE_TO_ARY:
409 rb_node_release(node->u1.node);
410 break;
411
412 case NODE_SCOPE: /* 2,3 */
413 case NODE_CDECL:
414 case NODE_OPT_ARG:
415 rb_node_release(node->u3.node);
416 rb_node_release(node->u2.node);
417 break;
418 }
419
420 // c--;
421
422 // Some NODE structures are apparently reused somewhere in parserland.
423 const int count = auto_zone_retain_count(__auto_zone, node);
424 if (count > 0) {
425 node->u1.node = node->u2.node = node->u3.node = NULL;
426 GC_RELEASE(node);
427 }
428 }
429
2ba4bd4 @lrz honor RData dfree() callback
lrz authored
430 static void
431 rdata_finalize(void *rcv, SEL sel)
432 {
433 if (RDATA(rcv)->dfree != NULL && RDATA(rcv)->data != NULL) {
434 RDATA(rcv)->dfree(RDATA(rcv)->data);
435 RDATA(rcv)->data = NULL;
436 }
437 }
438
9c1d230 committing experimental branch content
Laurent Sansonetti authored
439 VALUE
2ba4bd4 @lrz honor RData dfree() callback
lrz authored
440 rb_data_object_alloc(VALUE klass, void *datap, RUBY_DATA_FUNC dmark,
441 RUBY_DATA_FUNC dfree)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
442 {
2ba4bd4 @lrz honor RData dfree() callback
lrz authored
443 if (klass) {
444 Check_Type(klass, T_CLASS);
445 }
446
9c1d230 committing experimental branch content
Laurent Sansonetti authored
447 NEWOBJ(data, struct RData);
448 OBJSETUP(data, klass, T_DATA);
449 GC_WB(&data->data, datap);
450 data->dfree = dfree;
451 data->dmark = dmark;
452
2ba4bd4 @lrz honor RData dfree() callback
lrz authored
453 if (dfree != NULL) {
454 rb_objc_install_method2((Class)klass, "finalize", (IMP)rdata_finalize);
455 }
456
9c1d230 committing experimental branch content
Laurent Sansonetti authored
457 return (VALUE)data;
458 }
459
460 void
461 rb_gc_force_recycle(VALUE p)
462 {
08598db let's try to work around the parser crash with a gruik technique
Laurent Sansonetti authored
463 // FIXME this xfree call is commented because it's used by the parser which is NOT GC-safe at this point
464 // xfree((void *)p);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
465 }
466
467 static int
468 garbage_collect(void)
469 {
7ce865f fixed a problem that can occur on fast hardware: MacRuby was creating…
Laurent Sansonetti authored
470 if (!dont_gc) {
b73f76c @lrz better deterministic GC.start
lrz authored
471 objc_collect(OBJC_EXHAUSTIVE_COLLECTION);
7ce865f fixed a problem that can occur on fast hardware: MacRuby was creating…
Laurent Sansonetti authored
472 }
9c1d230 committing experimental branch content
Laurent Sansonetti authored
473 return Qtrue;
474 }
475
476 void
477 rb_gc(void)
478 {
479 garbage_collect();
480 }
481
482 /*
483 * call-seq:
484 * GC.start => nil
485 * gc.garbage_collect => nil
486 * ObjectSpace.garbage_collect => nil
487 *
488 * Initiates garbage collection, unless manually disabled.
489 *
490 */
491
492 VALUE
493 rb_gc_start(VALUE self, SEL sel)
494 {
495 rb_gc();
496 return Qnil;
497 }
498
499 /*
500 * Document-class: ObjectSpace
501 *
502 * The <code>ObjectSpace</code> module contains a number of routines
503 * that interact with the garbage collection facility and allow you to
504 * traverse all living objects with an iterator.
505 *
506 * <code>ObjectSpace</code> also provides support for object
507 * finalizers, procs that will be called when a specific object is
508 * about to be destroyed by garbage collection.
509 *
510 * include ObjectSpace
511 *
512 *
513 * a = "A"
514 * b = "B"
515 * c = "C"
516 *
517 *
518 * define_finalizer(a, proc {|id| puts "Finalizer one on #{id}" })
519 * define_finalizer(a, proc {|id| puts "Finalizer two on #{id}" })
520 * define_finalizer(b, proc {|id| puts "Finalizer three on #{id}" })
521 *
522 * <em>produces:</em>
523 *
524 * Finalizer three on 537763470
525 * Finalizer one on 537763480
526 * Finalizer two on 537763480
527 *
528 */
529
530 struct rb_objc_recorder_context {
531 VALUE class_of;
532 int count;
533 VALUE break_value;
534 };
535
536 static int
537 rb_objc_yield_classes(VALUE of)
538 {
bfcea02 @lrz fix Module objects to not inherit from Object, to behave like CRuby
lrz authored
539 const int count = objc_getClassList(NULL, 0);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
540 assert(count > 0);
541
bfcea02 @lrz fix Module objects to not inherit from Object, to behave like CRuby
lrz authored
542 Class *buf = (Class *)alloca(sizeof(Class) * count);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
543 objc_getClassList(buf, count);
bfcea02 @lrz fix Module objects to not inherit from Object, to behave like CRuby
lrz authored
544 const bool only_modules = of == rb_cModule;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
545
bfcea02 @lrz fix Module objects to not inherit from Object, to behave like CRuby
lrz authored
546 int rcount = 0;
547 for (int i = 0; i < count; i++) {
548 Class k = buf[i];
549 if (class_getName(k)[0] == '_') {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
550 continue;
bfcea02 @lrz fix Module objects to not inherit from Object, to behave like CRuby
lrz authored
551 }
9c1d230 committing experimental branch content
Laurent Sansonetti authored
552
bfcea02 @lrz fix Module objects to not inherit from Object, to behave like CRuby
lrz authored
553 if (only_modules) {
554 if (!RCLASS_MODULE(k)) {
555 continue;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
556 }
557 }
bfcea02 @lrz fix Module objects to not inherit from Object, to behave like CRuby
lrz authored
558 else {
559 bool nsobject_based = false;
560 Class sk = k;
561 do {
562 sk = (Class)RCLASS_SUPER(sk);
563 if (sk == (Class)rb_cNSObject) {
564 nsobject_based = true;
565 break;
566 }
567 }
568 while (sk != NULL);
569 if (!nsobject_based) {
570 continue;
571 }
9c1d230 committing experimental branch content
Laurent Sansonetti authored
572 }
bfcea02 @lrz fix Module objects to not inherit from Object, to behave like CRuby
lrz authored
573
574 rb_yield((VALUE)k);
575 RETURN_IF_BROKEN();
576 rcount++;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
577 }
578
579 return rcount;
580 }
581
582 static void
583 rb_objc_recorder(task_t task, void *context, unsigned type_mask,
d5a774d @lrz add rb_print_memory_objects() debug function
lrz authored
584 vm_range_t *ranges, unsigned range_count)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
585 {
586 struct rb_objc_recorder_context *ctx;
587 vm_range_t *r, *end;
588
589 ctx = (struct rb_objc_recorder_context *)context;
590
591 for (r = ranges, end = ranges + range_count; r < end; r++) {
2615970 fixed a few bugs in ObjectSpace#each_object
Laurent Sansonetti authored
592 auto_memory_type_t type = auto_zone_get_layout_type(__auto_zone,
593 (void *)r->address);
594 if (type != AUTO_OBJECT_SCANNED && type != AUTO_OBJECT_UNSCANNED) {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
595 continue;
2615970 fixed a few bugs in ObjectSpace#each_object
Laurent Sansonetti authored
596 }
597 if (*(Class *)r->address == NULL) {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
598 continue;
2615970 fixed a few bugs in ObjectSpace#each_object
Laurent Sansonetti authored
599 }
9c1d230 committing experimental branch content
Laurent Sansonetti authored
600 if (ctx->class_of != 0) {
2615970 fixed a few bugs in ObjectSpace#each_object
Laurent Sansonetti authored
601 Class c;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
602 bool ok = false;
2615970 fixed a few bugs in ObjectSpace#each_object
Laurent Sansonetti authored
603 for (c = *(Class *)r->address; c != NULL;
604 c = class_getSuperclass(c)) {
605 if (c == (Class)ctx->class_of) {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
606 ok = true;
607 break;
608 }
609 }
2615970 fixed a few bugs in ObjectSpace#each_object
Laurent Sansonetti authored
610 if (!ok) {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
611 continue;
2615970 fixed a few bugs in ObjectSpace#each_object
Laurent Sansonetti authored
612 }
9c1d230 committing experimental branch content
Laurent Sansonetti authored
613 }
614 switch (TYPE(r->address)) {
615 case T_NONE:
616 case T_NODE:
617 continue;
2615970 fixed a few bugs in ObjectSpace#each_object
Laurent Sansonetti authored
618
9c1d230 committing experimental branch content
Laurent Sansonetti authored
619 case T_ICLASS:
620 case T_CLASS:
621 case T_MODULE:
622 rb_bug("object %p of type %d should not be recorded",
623 (void *)r->address, TYPE(r->address));
624 }
625 rb_yield((VALUE)r->address);
626 ctx->break_value = rb_vm_pop_broken_value();
627 ctx->count++;
628 }
629 }
630
631 /*
632 * call-seq:
633 * ObjectSpace.each_object([module]) {|obj| ... } => fixnum
634 *
635 * Calls the block once for each living, nonimmediate object in this
636 * Ruby process. If <i>module</i> is specified, calls the block
637 * for only those classes or modules that match (or are a subclass of)
638 * <i>module</i>. Returns the number of objects found. Immediate
639 * objects (<code>Fixnum</code>s, <code>Symbol</code>s
640 * <code>true</code>, <code>false</code>, and <code>nil</code>) are
641 * never returned. In the example below, <code>each_object</code>
642 * returns both the numbers we defined and several constants defined in
643 * the <code>Math</code> module.
644 *
645 * a = 102.7
646 * b = 95 # Won't be returned
647 * c = 12345678987654321
648 * count = ObjectSpace.each_object(Numeric) {|x| p x }
649 * puts "Total count: #{count}"
650 *
651 * <em>produces:</em>
652 *
653 * 12345678987654321
654 * 102.7
655 * 2.71828182845905
656 * 3.14159265358979
657 * 2.22044604925031e-16
658 * 1.7976931348623157e+308
659 * 2.2250738585072e-308
660 * Total count: 7
661 *
662 */
663
664 static VALUE
665 os_each_obj(VALUE os, SEL sel, int argc, VALUE *argv)
666 {
667 VALUE of;
668 int count;
669
670 rb_secure(4);
671 if (argc == 0) {
672 of = 0;
673 }
674 else {
675 rb_scan_args(argc, argv, "01", &of);
676 }
677 RETURN_ENUMERATOR(os, 1, &of);
678
679 /* Class/Module are a special case, because they are not auto objects */
2615970 fixed a few bugs in ObjectSpace#each_object
Laurent Sansonetti authored
680 if (of == rb_cClass || of == rb_cModule) {
681 count = rb_objc_yield_classes(of);
682 }
683 else {
684 struct rb_objc_recorder_context ctx = {of, 0, Qundef};
9c1d230 committing experimental branch content
Laurent Sansonetti authored
685
2615970 fixed a few bugs in ObjectSpace#each_object
Laurent Sansonetti authored
686 auto_collector_disable(__auto_zone);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
687
688 (((malloc_zone_t *)__auto_zone)->introspect->enumerator)(
689 mach_task_self(), (void *)&ctx, MALLOC_PTR_IN_USE_RANGE_TYPE,
690 (vm_address_t)__auto_zone, NULL, rb_objc_recorder);
691
2615970 fixed a few bugs in ObjectSpace#each_object
Laurent Sansonetti authored
692 auto_collector_reenable(__auto_zone);
693
694 if (ctx.break_value != Qundef) {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
695 return ctx.break_value;
696 }
697
698 count = ctx.count;
699 }
700
701 return INT2FIX(count);
702 }
703
704 /*
705 * call-seq:
706 * ObjectSpace.undefine_finalizer(obj)
707 *
708 * Removes all finalizers for <i>obj</i>.
709 *
710 */
711
639c64d implemented ObjectSpace finalizers (experimental)
Laurent Sansonetti authored
712 static VALUE rb_cFinalizer;
713
714 static void *finalizer_key = NULL; // only used for its address
715
716 static IMP rb_objc_finalizer_finalize_super = NULL;
717
718 static void
719 rb_objc_finalizer_finalize(void *rcv, SEL sel)
720 {
721 rb_vm_finalizer_t *f = (rb_vm_finalizer_t *)rcv;
0b8411a call pending ObjectSpace finalizers before exiting
Laurent Sansonetti authored
722 rb_vm_call_finalizer(f);
723 rb_vm_unregister_finalizer(f);
639c64d implemented ObjectSpace finalizers (experimental)
Laurent Sansonetti authored
724 if (rb_objc_finalizer_finalize_super != NULL) {
725 ((void(*)(void *, SEL))rb_objc_finalizer_finalize_super)(rcv, sel);
726 }
727 }
9c1d230 committing experimental branch content
Laurent Sansonetti authored
728
729 static VALUE
730 undefine_final(VALUE os, SEL sel, VALUE obj)
731 {
639c64d implemented ObjectSpace finalizers (experimental)
Laurent Sansonetti authored
732 if (SPECIAL_CONST_P(obj)) {
733 rb_raise(rb_eArgError, "immediate types are not finalizable");
9c1d230 committing experimental branch content
Laurent Sansonetti authored
734 }
639c64d implemented ObjectSpace finalizers (experimental)
Laurent Sansonetti authored
735 rb_vm_finalizer_t *finalizer = rb_objc_get_associative_ref((void *)obj,
736 &finalizer_key);
737 if (finalizer != NULL) {
738 rb_ary_clear(finalizer->finalizers);
0b8411a call pending ObjectSpace finalizers before exiting
Laurent Sansonetti authored
739 rb_vm_unregister_finalizer(finalizer);
639c64d implemented ObjectSpace finalizers (experimental)
Laurent Sansonetti authored
740 rb_objc_set_associative_ref((void *)obj, &finalizer_key, NULL);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
741 }
742 return obj;
743 }
744
745 /*
746 * call-seq:
747 * ObjectSpace.define_finalizer(obj, aProc=proc())
748 *
749 * Adds <i>aProc</i> as a finalizer, to be called after <i>obj</i>
750 * was destroyed.
751 *
752 */
753
754 static VALUE
755 define_final(VALUE os, SEL sel, int argc, VALUE *argv)
756 {
639c64d implemented ObjectSpace finalizers (experimental)
Laurent Sansonetti authored
757 VALUE obj, block;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
758
759 rb_scan_args(argc, argv, "11", &obj, &block);
760 if (argc == 1) {
761 block = rb_block_proc();
762 }
763 else if (!rb_respond_to(block, rb_intern("call"))) {
764 rb_raise(rb_eArgError, "wrong type argument %s (should be callable)",
639c64d implemented ObjectSpace finalizers (experimental)
Laurent Sansonetti authored
765 rb_obj_classname(block));
9c1d230 committing experimental branch content
Laurent Sansonetti authored
766 }
767
639c64d implemented ObjectSpace finalizers (experimental)
Laurent Sansonetti authored
768 if (SPECIAL_CONST_P(obj)) {
769 rb_raise(rb_eArgError, "immediate types are not finalizable");
9c1d230 committing experimental branch content
Laurent Sansonetti authored
770 }
771
639c64d implemented ObjectSpace finalizers (experimental)
Laurent Sansonetti authored
772 rb_vm_finalizer_t *finalizer = rb_objc_get_associative_ref((void *)obj,
773 &finalizer_key);
774 if (finalizer == NULL) {
775 finalizer = (rb_vm_finalizer_t *)
776 rb_objc_newobj(sizeof(rb_vm_finalizer_t *));
777 finalizer->klass = rb_cFinalizer;
0b8411a call pending ObjectSpace finalizers before exiting
Laurent Sansonetti authored
778 finalizer->objid = rb_obj_id(obj, 0);
639c64d implemented ObjectSpace finalizers (experimental)
Laurent Sansonetti authored
779 GC_WB(&finalizer->finalizers, rb_ary_new());
780 rb_objc_set_associative_ref((void *)obj, &finalizer_key, finalizer);
0b8411a call pending ObjectSpace finalizers before exiting
Laurent Sansonetti authored
781 rb_vm_register_finalizer(finalizer);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
782 }
32a181b fixed the return value of ObjectSpace#define_finalizer
Laurent Sansonetti authored
783
639c64d implemented ObjectSpace finalizers (experimental)
Laurent Sansonetti authored
784 rb_ary_push(finalizer->finalizers, block);
785
786 // For RubySpec conformance.
787 return rb_ary_new3(2, INT2FIX(rb_safe_level()), block);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
788 }
789
790 void
791 rb_gc_copy_finalizer(VALUE dest, VALUE obj)
792 {
639c64d implemented ObjectSpace finalizers (experimental)
Laurent Sansonetti authored
793 // TODO
9c1d230 committing experimental branch content
Laurent Sansonetti authored
794 }
795
796 /*
797 * call-seq:
798 * ObjectSpace._id2ref(object_id) -> an_object
799 *
800 * Converts an object id to a reference to the object. May not be
801 * called on an object id passed as a parameter to a finalizer.
802 *
803 * s = "I am a string" #=> "I am a string"
804 * r = ObjectSpace._id2ref(s.object_id) #=> "I am a string"
805 * r == s #=> true
806 *
807 */
808
809 static VALUE
22e5dfa fixed ObjectSpace#_id2ref
Laurent Sansonetti authored
810 id2ref(VALUE obj, SEL sel, VALUE objid)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
811 {
812 #if SIZEOF_LONG == SIZEOF_VOIDP
813 #define NUM2PTR(x) NUM2ULONG(x)
814 #elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
815 #define NUM2PTR(x) NUM2ULL(x)
816 #endif
817 VALUE ptr;
818 void *p0;
819
820 rb_secure(4);
821 ptr = NUM2PTR(objid);
822 p0 = (void *)ptr;
823
824 if (ptr == Qtrue) return Qtrue;
825 if (ptr == Qfalse) return Qfalse;
826 if (ptr == Qnil) return Qnil;
827 if (FIXNUM_P(ptr) || SYMBOL_P(ptr))
828 return ptr;
829
c9656af <rdar://problem/7752412>
Laurent Sansonetti authored
830 if (auto_zone_is_valid_pointer(__auto_zone, p0)) {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
831 auto_memory_type_t type =
832 auto_zone_get_layout_type(__auto_zone, p0);
833 if ((type == AUTO_OBJECT_SCANNED || type == AUTO_OBJECT_UNSCANNED)
834 && (NATIVE((VALUE)p0)
835 || (BUILTIN_TYPE(p0) < T_FIXNUM && BUILTIN_TYPE(p0) != T_ICLASS)))
836 return (VALUE)p0;
837 }
838 rb_raise(rb_eRangeError, "%p is not id value", p0);
839 }
840
841 /*
842 * Document-method: __id__
843 * Document-method: object_id
844 *
845 * call-seq:
846 * obj.__id__ => fixnum
847 * obj.object_id => fixnum
848 *
849 * Returns an integer identifier for <i>obj</i>. The same number will
850 * be returned on all calls to <code>id</code> for a given object, and
851 * no two active objects will share an id.
852 * <code>Object#object_id</code> is a different concept from the
853 * <code>:name</code> notation, which returns the symbol id of
854 * <code>name</code>. Replaces the deprecated <code>Object#id</code>.
855 */
856
857 /*
858 * call-seq:
859 * obj.hash => fixnum
860 *
861 * Generates a <code>Fixnum</code> hash value for this object. This
862 * function must have the property that <code>a.eql?(b)</code> implies
863 * <code>a.hash == b.hash</code>. The hash value is used by class
864 * <code>Hash</code>. Any hash value that exceeds the capacity of a
865 * <code>Fixnum</code> will be truncated before being used.
866 */
867
ccab368 don't touch -[NSObject hash]
Laurent Sansonetti authored
868 VALUE
9c1d230 committing experimental branch content
Laurent Sansonetti authored
869 rb_obj_id(VALUE obj, SEL sel)
870 {
871 return (VALUE)LONG2NUM((SIGNED_VALUE)obj);
872 }
873
874 /*
875 * call-seq:
876 * ObjectSpace.count_objects([result_hash]) -> hash
877 *
878 * Counts objects for each type.
879 *
880 * It returns a hash as:
881 * {:TOTAL=>10000, :FREE=>3011, :T_OBJECT=>6, :T_CLASS=>404, ...}
882 *
883 * If the optional argument, result_hash, is given,
884 * it is overwritten and returned.
885 * This is intended to avoid probe effect.
886 *
887 * The contents of the returned hash is implementation defined.
888 * It may be changed in future.
889 *
890 * This method is not expected to work except C Ruby.
891 *
892 */
893
894 static VALUE
895 count_objects(VALUE os, SEL sel, int argc, VALUE *argv)
896 {
897 /* TODO implement me! */
898 return rb_hash_new();
899 #if 0
900 rb_objspace_t *objspace = &rb_objspace;
901 size_t counts[T_MASK+1];
902 size_t freed = 0;
903 size_t total = 0;
904 size_t i;
905 VALUE hash;
906
907 if (rb_scan_args(argc, argv, "01", &hash) == 1) {
908 if (TYPE(hash) != T_HASH)
909 rb_raise(rb_eTypeError, "non-hash given");
910 }
911
912 for (i = 0; i <= T_MASK; i++) {
913 counts[i] = 0;
914 }
915
916 for (i = 0; i < heaps_used; i++) {
917 RVALUE *p, *pend;
918
919 p = heaps[i].slot; pend = p + heaps[i].limit;
920 for (;p < pend; p++) {
921 if (p->as.basic.flags) {
922 counts[BUILTIN_TYPE(p)]++;
923 }
924 else {
925 freed++;
926 }
927 }
928 total += heaps[i].limit;
929 }
930
931 if (hash == Qnil)
932 hash = rb_hash_new();
933 rb_hash_aset(hash, ID2SYM(rb_intern("TOTAL")), SIZET2NUM(total));
934 rb_hash_aset(hash, ID2SYM(rb_intern("FREE")), SIZET2NUM(freed));
935 for (i = 0; i <= T_MASK; i++) {
936 VALUE type;
937 switch (i) {
938 #define COUNT_TYPE(t) case t: type = ID2SYM(rb_intern(#t)); break;
939 COUNT_TYPE(T_NONE);
940 COUNT_TYPE(T_OBJECT);
941 COUNT_TYPE(T_CLASS);
942 COUNT_TYPE(T_MODULE);
943 COUNT_TYPE(T_FLOAT);
944 COUNT_TYPE(T_STRING);
945 COUNT_TYPE(T_REGEXP);
946 COUNT_TYPE(T_ARRAY);
947 COUNT_TYPE(T_HASH);
948 COUNT_TYPE(T_STRUCT);
949 COUNT_TYPE(T_BIGNUM);
950 COUNT_TYPE(T_FILE);
951 COUNT_TYPE(T_DATA);
952 COUNT_TYPE(T_MATCH);
953 COUNT_TYPE(T_COMPLEX);
954 COUNT_TYPE(T_RATIONAL);
955 COUNT_TYPE(T_NIL);
956 COUNT_TYPE(T_TRUE);
957 COUNT_TYPE(T_FALSE);
958 COUNT_TYPE(T_SYMBOL);
959 COUNT_TYPE(T_FIXNUM);
960 COUNT_TYPE(T_VALUES);
961 COUNT_TYPE(T_UNDEF);
962 COUNT_TYPE(T_NODE);
963 COUNT_TYPE(T_ICLASS);
964 #undef COUNT_TYPE
965 default: type = INT2NUM(i); break;
966 }
967 if (counts[i])
968 rb_hash_aset(hash, type, SIZET2NUM(counts[i]));
969 }
970
971 return hash;
972 #endif
973 }
974
975 /*
976 * call-seq:
977 * GC.count -> Integer
978 *
979 * The number of times GC occured.
980 *
981 * It returns the number of times GC occured since the process started.
982 *
983 */
984
c177343 GC.count: deleted implementation, marked as not-implemented
Laurent Sansonetti authored
985 #define gc_count rb_f_notimplement
9c1d230 committing experimental branch content
Laurent Sansonetti authored
986
987 /*
988 * The <code>GC</code> module provides an interface to Ruby's mark and
989 * sweep garbage collection mechanism. Some of the underlying methods
990 * are also available via the <code>ObjectSpace</code> module.
991 */
992
993 static bool gc_disabled = false;
994
995 void
996 Init_PreGC(void)
997 {
998 auto_collection_control_t *control;
999
c9656af <rdar://problem/7752412>
Laurent Sansonetti authored
1000 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
1001 __auto_zone = objc_collectableZone();
52ad160 woops
Laurent Sansonetti authored
1002 #else
1003 __auto_zone = auto_zone();
c9656af <rdar://problem/7752412>
Laurent Sansonetti authored
1004 #endif
9c1d230 committing experimental branch content
Laurent Sansonetti authored
1005
1006 if (__auto_zone == NULL) {
1007 rb_objc_no_gc_error();
1008 }
1009
1010 __nsobject = (void *)objc_getClass("NSObject");
1011
1012 control = auto_collection_parameters(__auto_zone);
1013 if (getenv("GC_DEBUG")) {
1014 control->log = AUTO_LOG_COLLECTIONS | AUTO_LOG_REGIONS | AUTO_LOG_UNUSUAL;
1015 }
1016 if (getenv("GC_DISABLE")) {
1017 gc_disabled = true;
8c990c5 don't temporarily disable the collector when booting the interpreter
Laurent Sansonetti authored
1018 auto_collector_disable(__auto_zone);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
1019 }
1020 }
1021
1022 void
1023 Init_PostGC(void)
1024 {
1025 if (!gc_disabled) {
a4b25e7 don't call objc_startCollectorThread() on the bleeding edge
Laurent Sansonetti authored
1026 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1070
9c1d230 committing experimental branch content
Laurent Sansonetti authored
1027 objc_startCollectorThread();
a4b25e7 don't call objc_startCollectorThread() on the bleeding edge
Laurent Sansonetti authored
1028 #endif
9c1d230 committing experimental branch content
Laurent Sansonetti authored
1029 }
1030 }
1031
1032 void
1033 Init_GC(void)
1034 {
1035 VALUE rb_mObSpace;
1036
1037 rb_mGC = rb_define_module("GC");
3eaff0d define the GC and ObjectSpace API as module functions
Laurent Sansonetti authored
1038 rb_objc_define_module_function(rb_mGC, "start", rb_gc_start, 0);
1039 rb_objc_define_module_function(rb_mGC, "enable", rb_gc_enable, 0);
1040 rb_objc_define_module_function(rb_mGC, "disable", rb_gc_disable, 0);
1041 rb_objc_define_module_function(rb_mGC, "stress", gc_stress_get, 0);
1042 rb_objc_define_module_function(rb_mGC, "stress=", gc_stress_set, 1);
1043 rb_objc_define_module_function(rb_mGC, "count", gc_count, 0);
bdf345a Improve core/gc pass rate
Thibault Martin-Lagardette authored
1044 rb_objc_define_method(rb_mGC, "garbage_collect", rb_gc_start, 0);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
1045
1046 rb_mObSpace = rb_define_module("ObjectSpace");
3eaff0d define the GC and ObjectSpace API as module functions
Laurent Sansonetti authored
1047 rb_objc_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1);
1048 rb_objc_define_module_function(rb_mObSpace, "garbage_collect", rb_gc_start, 0);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
1049
3eaff0d define the GC and ObjectSpace API as module functions
Laurent Sansonetti authored
1050 rb_objc_define_module_function(rb_mObSpace, "define_finalizer", define_final, -1);
1051 rb_objc_define_module_function(rb_mObSpace, "undefine_finalizer", undefine_final, 1);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
1052
3eaff0d define the GC and ObjectSpace API as module functions
Laurent Sansonetti authored
1053 rb_objc_define_module_function(rb_mObSpace, "_id2ref", id2ref, 1);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
1054
1055 nomem_error = rb_exc_new2(rb_eNoMemError, "failed to allocate memory");
8e4c2c7 moving the dispatcher bits into the kernel + misc fixes/cleanup
Laurent Sansonetti authored
1056 GC_RETAIN(nomem_error);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
1057
1058 rb_objc_define_method(rb_mKernel, "__id__", rb_obj_id, 0);
1059 rb_objc_define_method(rb_mKernel, "object_id", rb_obj_id, 0);
1060
3eaff0d define the GC and ObjectSpace API as module functions
Laurent Sansonetti authored
1061 rb_objc_define_module_function(rb_mObSpace, "count_objects", count_objects, -1);
639c64d implemented ObjectSpace finalizers (experimental)
Laurent Sansonetti authored
1062
1063 rb_cFinalizer = rb_define_class("__Finalizer", rb_cObject);
1064 rb_objc_finalizer_finalize_super =
1065 rb_objc_install_method2((Class)rb_cFinalizer,
1066 "finalize", (IMP)rb_objc_finalizer_finalize);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
1067 }
32133a1 add implementation for MRI rb_global_variable() API (important: not t…
Laurent Sansonetti authored
1068
1069 void
1070 rb_global_variable(VALUE *slot)
1071 {
1072 auto_zone_add_root(__auto_zone, (void *)slot, *(void **)slot);
1073 }
ac9d685 add rb_gc_register_address() MRI API
Laurent Sansonetti authored
1074
1075 void
1076 rb_gc_register_address(VALUE *slot)
1077 {
1078 rb_global_variable(slot);
1079 }
d5a774d @lrz add rb_print_memory_objects() debug function
lrz authored
1080
1081 static void
1082 print_memory_object(task_t task, void *context, unsigned type_mask,
1083 vm_range_t *ranges, unsigned range_count)
1084 {
1085 const size_t min_size = *(size_t *)context;
1086 for (vm_range_t *r = ranges, *end = ranges + range_count; r < end; r++) {
1087 const size_t size = auto_zone_size(__auto_zone, (void *)r->address);
1088 if (size >= min_size) {
c1833dd @lrz some work on garbage collecting singleton classes - disabled for now …
lrz authored
1089 printf("address %p size %ld rc %d layout type ",
1090 (void *)r->address, size,
1091 auto_zone_retain_count(__auto_zone, (void *)r->address));
d5a774d @lrz add rb_print_memory_objects() debug function
lrz authored
1092 switch (auto_zone_get_layout_type(__auto_zone,
1093 (void *)r->address)) {
1094 case AUTO_OBJECT:
1095 printf("object (class %s)\n",
1096 class_getName(object_getClass((void *)r->address)));
1097 break;
1098 default:
1099 printf("memory\n");
1100 break;
1101 }
1102 }
1103 }
1104 }
1105
1106 void
1107 rb_print_memory_objects(size_t min_size)
1108 {
1109 (((malloc_zone_t *)__auto_zone)->introspect->enumerator)(mach_task_self(),
1110 (void *)&min_size, MALLOC_PTR_IN_USE_RANGE_TYPE,
1111 (vm_address_t)__auto_zone, NULL, print_memory_object);
1112 }
Something went wrong with that request. Please try again.