~ubuntu-branches/ubuntu/quantal/ruby1.9.1/quantal

« back to all changes in this revision

Viewing changes to ext/objspace/objspace.c

  • Committer: Bazaar Package Importer
  • Author(s): Lucas Nussbaum
  • Date: 2011-09-24 19:16:17 UTC
  • mfrom: (1.1.8 upstream) (13.1.7 experimental)
  • Revision ID: james.westby@ubuntu.com-20110924191617-o1qz4rcmqjot8zuy
Tags: 1.9.3~rc1-1
* New upstream release: 1.9.3 RC1.
  + Includes load.c fixes. Closes: #639959.
* Upload to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 
3
3
  objspace.c - ObjectSpace extender for MRI.
4
4
 
5
 
  $Author: yugui $
 
5
  $Author: ktsj $
6
6
  created at: Wed Jun 17 07:39:17 2009
7
7
 
8
8
  NOTE: This extension library is not expected to exist except C Ruby.
27
27
#include <ruby/st.h>
28
28
#include <ruby/io.h>
29
29
#include <ruby/re.h>
30
 
#include <../../node.h>
 
30
#include "node.h"
 
31
#include "gc.h"
 
32
#include "regint.h"
 
33
#include "internal.h"
31
34
 
32
35
size_t rb_str_memsize(VALUE);
33
36
size_t rb_ary_memsize(VALUE);
34
 
size_t rb_io_memsize(rb_io_t *);
35
 
size_t onig_memsize(regex_t *);
 
37
size_t rb_io_memsize(const rb_io_t *);
36
38
size_t rb_generic_ivar_memsize(VALUE);
37
39
size_t rb_objspace_data_type_memsize(VALUE obj);
38
40
 
39
 
void rb_objspace_each_objects(
40
 
    int (*callback)(void *start, void *end, size_t stride, void *data),
41
 
    void *data);
42
 
 
43
41
static size_t
44
42
memsize_of(VALUE obj)
45
43
{
72
70
        if (RCLASS(obj)->ptr->iv_tbl) {
73
71
            size += st_memsize(RCLASS(obj)->ptr->iv_tbl);
74
72
        }
 
73
        if (RCLASS(obj)->ptr->const_tbl) {
 
74
            size += st_memsize(RCLASS(obj)->ptr->const_tbl);
 
75
        }
75
76
        size += sizeof(rb_classext_t);
76
77
        break;
77
78
      case T_STRING:
158
159
 *
159
160
 *  Return consuming memory size of obj.
160
161
 *
161
 
 *  Note that this information is incomplete.  You need to deal with
162
 
 *  this information as only a *HINT*.  Especaially, the size of
163
 
 *  T_DATA may not right size.
 
162
 *  Note that the return size is incomplete.  You need to deal with
 
163
 *  this information as only a *HINT*.  Especially, the size of
 
164
 *  T_DATA may not be correct.
164
165
 *
165
166
 *  This method is not expected to work except C Ruby.
166
167
 */
171
172
    return SIZET2NUM(memsize_of(obj));
172
173
}
173
174
 
 
175
struct total_data {
 
176
    size_t total;
 
177
    VALUE klass;
 
178
};
 
179
 
 
180
static int
 
181
total_i(void *vstart, void *vend, size_t stride, void *ptr)
 
182
{
 
183
    VALUE v;
 
184
    struct total_data *data = (struct total_data *)ptr;
 
185
 
 
186
    for (v = (VALUE)vstart; v != (VALUE)vend; v += stride) {
 
187
        if (RBASIC(v)->flags) {
 
188
            switch (BUILTIN_TYPE(v)) {
 
189
              case T_NONE:
 
190
              case T_ICLASS:
 
191
              case T_NODE:
 
192
              case T_ZOMBIE:
 
193
                continue;
 
194
              case T_CLASS:
 
195
                if (FL_TEST(v, FL_SINGLETON))
 
196
                  continue;
 
197
              default:
 
198
                if (data->klass == 0 || rb_obj_is_kind_of(v, data->klass)) {
 
199
                    data->total += memsize_of(v);
 
200
                }
 
201
            }
 
202
        }
 
203
    }
 
204
 
 
205
    return 0;
 
206
}
 
207
 
 
208
/*
 
209
 *  call-seq:
 
210
 *    ObjectSpace.memsize_of_all([klass]) -> Integer
 
211
 *
 
212
 *  Return consuming memory size of all living objects.
 
213
 *  If klass (should be Class object) is given, return the total
 
214
 *  memory size of instances of the given class.
 
215
 *
 
216
 *  Note that the returned size is incomplete.  You need to deal with
 
217
 *  this information as only a *HINT*.  Especially, the size of
 
218
 *  T_DATA may not be correct.
 
219
 *
 
220
 *  Note that this method does *NOT* return total malloc'ed memory size.
 
221
 *
 
222
 *  This method can be defined by the following Ruby code:
 
223
 *
 
224
 *  def memsize_of_all klass = false
 
225
 *    total = 0
 
226
 *    ObjectSpace.each_objects{|e|
 
227
 *      total += ObjectSpace.memsize_of(e) if klass == false || e.kind_of?(klass)
 
228
 *    }
 
229
 *    total
 
230
 *  end
 
231
 *
 
232
 *  This method is not expected to work except C Ruby.
 
233
 */
 
234
 
 
235
static VALUE
 
236
memsize_of_all_m(int argc, VALUE *argv, VALUE self)
 
237
{
 
238
    struct total_data data = {0, 0};
 
239
 
 
240
    if (argc > 0) {
 
241
        rb_scan_args(argc, argv, "01", &data.klass);
 
242
    }
 
243
 
 
244
    rb_objspace_each_objects(total_i, &data);
 
245
    return SIZET2NUM(data.total);
 
246
}
 
247
 
174
248
static int
175
249
set_zero_i(st_data_t key, st_data_t val, st_data_t arg)
176
250
{
201
275
 *  Counts objects size (in bytes) for each type.
202
276
 *
203
277
 *  Note that this information is incomplete.  You need to deal with
204
 
 *  this information as only a *HINT*.  Especaially, total size of
 
278
 *  this information as only a *HINT*.  Especially, total size of
205
279
 *  T_DATA may not right size.
206
280
 *
207
281
 *  It returns a hash as:
473
547
 
474
548
    for (; v != (VALUE)vend; v += stride) {
475
549
        if (RBASIC(v)->flags && BUILTIN_TYPE(v) == T_DATA) {
476
 
            VALUE counter = rb_hash_aref(hash, RBASIC(v)->klass);
 
550
            VALUE counter;
 
551
            VALUE key = RBASIC(v)->klass;
 
552
 
 
553
            if (key == 0) {
 
554
                const char *name = rb_objspace_data_type_name(v);
 
555
                if (name == 0) name = "unknown";
 
556
                key = ID2SYM(rb_intern(name));
 
557
            }
 
558
 
 
559
            counter = rb_hash_aref(hash, key);
477
560
            if (NIL_P(counter)) {
478
561
                counter = INT2FIX(1);
479
562
            }
480
563
            else {
481
564
                counter = INT2FIX(FIX2INT(counter) + 1);
482
565
            }
483
 
            rb_hash_aset(hash, RBASIC(v)->klass, counter);
 
566
 
 
567
            rb_hash_aset(hash, key, counter);
484
568
        }
485
569
    }
486
570
 
491
575
 *  call-seq:
492
576
 *     ObjectSpace.count_tdata_objects([result_hash]) -> hash
493
577
 *
494
 
 *  Counts nodes for each node type.
 
578
 *  Counts objects for each T_DATA type.
495
579
 *
496
580
 *  This method is not for ordinary Ruby programmers, but for MRI developers
497
581
 *  who interest on MRI performance.
498
582
 *
499
583
 *  It returns a hash as:
500
 
 *  {:NODE_METHOD=>2027, :NODE_FBODY=>1927, :NODE_CFUNC=>1798, ...}
 
584
 *  {RubyVM::InstructionSequence=>504, :parser=>5, :barrier=>6,
 
585
 *   :mutex=>6, Proc=>60, RubyVM::Env=>57, Mutex=>1, Encoding=>99,
 
586
 *   ThreadGroup=>1, Binding=>1, Thread=>1, RubyVM=>1, :iseq=>1,
 
587
 *   Random=>1, ARGF.class=>1, Data=>1, :autoload=>3, Time=>2}
 
588
 *  # T_DATA objects existing at startup on r32276.
501
589
 *
502
590
 *  If the optional argument, result_hash, is given,
503
591
 *  it is overwritten and returned.
506
594
 *  The contents of the returned hash is implementation defined.
507
595
 *  It may be changed in future.
508
596
 *
 
597
 *  In this version, keys are Class object or Symbol object.
 
598
 *  If object is kind of normal (accessible) object, the key is Class object.
 
599
 *  If object is not a kind of normal (internal) object, the key is symbol
 
600
 *  name, registered by rb_data_type_struct.
 
601
 *
509
602
 *  This method is not expected to work except C Ruby.
510
603
 *
511
604
 */
547
640
{
548
641
    VALUE rb_mObjSpace = rb_const_get(rb_cObject, rb_intern("ObjectSpace"));
549
642
 
 
643
    rb_define_module_function(rb_mObjSpace, "memsize_of", memsize_of_m, 1);
 
644
    rb_define_module_function(rb_mObjSpace, "memsize_of_all",
 
645
                              memsize_of_all_m, -1);
 
646
 
550
647
    rb_define_module_function(rb_mObjSpace, "count_objects_size", count_objects_size, -1);
551
 
    rb_define_module_function(rb_mObjSpace, "memsize_of", memsize_of_m, 1);
552
648
    rb_define_module_function(rb_mObjSpace, "count_nodes", count_nodes, -1);
553
649
    rb_define_module_function(rb_mObjSpace, "count_tdata_objects", count_tdata_objects, -1);
554
650
}