heap_dump 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/ext/heap_dump/heap_dump.c +70 -15
- data/lib/heap_dump/version.rb +1 -1
- metadata +8 -8
data/ext/heap_dump/heap_dump.c
CHANGED
@@ -69,6 +69,8 @@ static void flush_yajl(walk_ctx_t *ctx){
|
|
69
69
|
}
|
70
70
|
}
|
71
71
|
|
72
|
+
static inline int is_pointer_to_heap(void *ptr, void* osp);
|
73
|
+
|
72
74
|
static inline const char* rb_builtin_type(VALUE obj){
|
73
75
|
switch(BUILTIN_TYPE(obj)){
|
74
76
|
#define T(t) case t: return #t;
|
@@ -343,8 +345,17 @@ static void dump_node_refs(NODE* obj, walk_ctx_t* ctx){
|
|
343
345
|
|
344
346
|
//iteration func - blocks,procs,lambdas etc:
|
345
347
|
case NODE_IFUNC: //NEN_CFNC, NEN_TVAL, NEN_STATE? / u2 seems to be data for func(context?)
|
346
|
-
|
348
|
+
printf("IFUNC NODE: %p %p %p\n", obj->nd_cfnc, obj->u2.node, (void*)obj->nd_aid /*u3 - aid id- - aka frame_this_func?*/);
|
347
349
|
//FIXME: closures may leak references?
|
350
|
+
if(is_pointer_to_heap(obj->u2.node, 0)){
|
351
|
+
printf("in heap: %p\n", obj->u2.node);
|
352
|
+
//TODO: do we need to dump it inline?
|
353
|
+
yg_id(obj->u2.node);
|
354
|
+
}
|
355
|
+
if(is_pointer_to_heap( (void*)obj->nd_aid, 0)){
|
356
|
+
printf("in heap: %p\n", (void*)obj->nd_aid);
|
357
|
+
yg_id(obj->nd_aid);
|
358
|
+
}
|
348
359
|
break;
|
349
360
|
|
350
361
|
//empty:
|
@@ -396,32 +407,27 @@ static void dump_hash(VALUE obj, walk_ctx_t* ctx){
|
|
396
407
|
yajl_gen_map_close(ctx->yajl);
|
397
408
|
}
|
398
409
|
|
399
|
-
static
|
400
|
-
walk_ctx_t *ctx = (void*)data;
|
401
|
-
if(key == ID_ALLOCATOR) {
|
402
|
-
yg_cstring("___allocator___");
|
403
|
-
} else {
|
404
|
-
yg_cstring(rb_id2name(key));
|
405
|
-
}
|
406
|
-
|
407
|
-
const rb_method_definition_t *def = me->def;
|
408
|
-
|
409
|
-
//gc_mark(objspace, me->klass, lev);?
|
410
|
+
static void dump_method_definition_as_value(const rb_method_definition_t *def, walk_ctx_t *ctx){
|
410
411
|
if (!def) {
|
411
412
|
yajl_gen_null(ctx->yajl);
|
412
|
-
return
|
413
|
+
return;
|
413
414
|
}
|
415
|
+
//printf("mdef %d\n", def->type);
|
414
416
|
|
415
417
|
switch (def->type) {
|
416
418
|
case VM_METHOD_TYPE_ISEQ:
|
419
|
+
//printf("method iseq %p\n", def->body.iseq);
|
420
|
+
//printf("self %p\n", def->body.iseq->self);
|
417
421
|
yg_id(def->body.iseq->self);
|
418
422
|
break;
|
419
423
|
case VM_METHOD_TYPE_CFUNC: yg_cstring("(CFUNC)"); break;
|
420
424
|
case VM_METHOD_TYPE_ATTRSET:
|
421
425
|
case VM_METHOD_TYPE_IVAR:
|
426
|
+
//printf("method ivar\n");
|
422
427
|
yg_id(def->body.attr.location);
|
423
428
|
break;
|
424
429
|
case VM_METHOD_TYPE_BMETHOD:
|
430
|
+
//printf("method binary\n");
|
425
431
|
yg_id(def->body.proc);
|
426
432
|
break;
|
427
433
|
case VM_METHOD_TYPE_ZSUPER: yg_cstring("(ZSUPER)"); break;
|
@@ -433,6 +439,19 @@ static int dump_method_entry_i(ID key, const rb_method_entry_t *me, st_data_t da
|
|
433
439
|
yajl_gen_null(ctx->yajl);
|
434
440
|
break;
|
435
441
|
}
|
442
|
+
}
|
443
|
+
|
444
|
+
static int dump_method_entry_i(ID key, const rb_method_entry_t *me, st_data_t data){
|
445
|
+
walk_ctx_t *ctx = (void*)data;
|
446
|
+
if(key == ID_ALLOCATOR) {
|
447
|
+
yg_cstring("___allocator___");
|
448
|
+
} else {
|
449
|
+
yg_cstring(rb_id2name(key));
|
450
|
+
}
|
451
|
+
|
452
|
+
//gc_mark(objspace, me->klass, lev);?
|
453
|
+
//printf("method entry\n");
|
454
|
+
dump_method_definition_as_value(me->def, ctx);
|
436
455
|
return ST_CONTINUE;
|
437
456
|
}
|
438
457
|
|
@@ -501,13 +520,21 @@ void dump_iseq(const rb_iseq_t* iseq, walk_ctx_t *ctx){
|
|
501
520
|
}
|
502
521
|
}
|
503
522
|
|
523
|
+
//!!! from 1.9.2-p290
|
524
|
+
struct METHOD {
|
525
|
+
VALUE recv;
|
526
|
+
VALUE rclass;
|
527
|
+
ID id;
|
528
|
+
rb_method_entry_t me;
|
529
|
+
};
|
530
|
+
|
504
531
|
void dump_data_if_known(VALUE obj, walk_ctx_t *ctx){
|
505
532
|
|
506
533
|
// VM
|
507
534
|
// VM/env
|
508
535
|
// VM/thread
|
509
536
|
// autoload
|
510
|
-
// binding
|
537
|
+
// binding <-
|
511
538
|
// encoding
|
512
539
|
// iseq <-
|
513
540
|
// method <-
|
@@ -544,6 +571,33 @@ void dump_data_if_known(VALUE obj, walk_ctx_t *ctx){
|
|
544
571
|
return;
|
545
572
|
}
|
546
573
|
|
574
|
+
if(!strcmp("method", typename)){
|
575
|
+
//printf("method\n");
|
576
|
+
struct METHOD *data = RTYPEDDATA_DATA(obj);
|
577
|
+
//printf("method %p: %p %p\n", data, data->rclass, data->recv);
|
578
|
+
ygh_id("rclass", data->rclass);
|
579
|
+
ygh_id("recv", data->recv);
|
580
|
+
ygh_int("method_id", data->id);
|
581
|
+
|
582
|
+
yg_cstring("method");
|
583
|
+
if(data->me.def){
|
584
|
+
//printf("methof def %p\n", &data->me);
|
585
|
+
dump_method_definition_as_value(data->me.def, ctx);
|
586
|
+
//printf("meth end\n");
|
587
|
+
}
|
588
|
+
return;
|
589
|
+
}
|
590
|
+
|
591
|
+
if(!strcmp("binding", typename)){
|
592
|
+
//printf("binding\n");
|
593
|
+
rb_binding_t *bind = RTYPEDDATA_DATA(obj);
|
594
|
+
//printf("binding %p\n", bind);
|
595
|
+
if(!bind) return;
|
596
|
+
ygh_id("env", bind->env);
|
597
|
+
ygh_id("filename", bind->filename);
|
598
|
+
return;
|
599
|
+
}
|
600
|
+
|
547
601
|
if(!strcmp("VM/env", typename)){
|
548
602
|
const rb_env_t* env = RTYPEDDATA_DATA(obj);
|
549
603
|
int i = 0;
|
@@ -1077,8 +1131,9 @@ typedef struct rb_objspace {
|
|
1077
1131
|
#define RANY(o) ((RVALUE*)(o))
|
1078
1132
|
|
1079
1133
|
static inline int
|
1080
|
-
is_pointer_to_heap(void *ptr,
|
1134
|
+
is_pointer_to_heap(void *ptr, void* osp)
|
1081
1135
|
{
|
1136
|
+
rb_objspace_t *objspace = osp;
|
1082
1137
|
if(!ptr) return false;
|
1083
1138
|
if(!objspace) objspace = GET_THREAD()->vm->objspace;
|
1084
1139
|
|
data/lib/heap_dump/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: heap_dump
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-05-
|
12
|
+
date: 2012-05-30 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ruby-internal
|
16
|
-
requirement: &
|
16
|
+
requirement: &70171206252720 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 0.8.5
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70171206252720
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: yajl-ruby
|
27
|
-
requirement: &
|
27
|
+
requirement: &70171206251900 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '1.1'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70171206251900
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rake-compiler
|
38
|
-
requirement: &
|
38
|
+
requirement: &70171206251120 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,7 +43,7 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70171206251120
|
47
47
|
description: dump ruby 1.9 heap contents
|
48
48
|
email:
|
49
49
|
- vasilyfedoseyev@gmail.com
|