objspace_helpers 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +24 -0
- data/Rakefile +20 -0
- data/ext/objspace_helpers/extconf.rb +5 -0
- data/ext/objspace_helpers/objspace_helpers.c +60 -0
- data/ext/objspace_helpers/objspace_helpers.h +10 -0
- data/ext/objspace_helpers/objspace_info.c +175 -0
- data/ext/objspace_helpers/objspace_info.h +15 -0
- data/ext/objspace_helpers/ruby_private/gc.h +107 -0
- data/ext/objspace_helpers/ruby_private/internal_defs.h +87 -0
- data/ext/objspace_helpers/ruby_private/objspace.h +15 -0
- data/lib/objspace_helpers/helpers.rb +28 -0
- data/lib/objspace_helpers/version.rb +3 -0
- data/lib/objspace_helpers.rb +6 -0
- metadata +99 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c64bb3dba9f6e3592d48191859735a4a982057d4
|
4
|
+
data.tar.gz: af65ffc525b86d06a64c0bcd75852512408bee98
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 07223b0ee7fe06143270fd91f66f07da4a324e832e57875b4941bd3059eb9e40da01dbae0e127624f21dc0a012c9c6a855cd682e8ece0a7e6b69716d97052621
|
7
|
+
data.tar.gz: 31e9b72f8f15653f86b2853965470504b82c9165370315a8ba520b4d98df8360023f0490b4affe5ef74ccad0e39cc88c3f2758dd5f8fd73485c02044006df4cc
|
data/LICENSE
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
Copyright (c) 2014, Lukas Fittl <lukas@fittl.com>
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
* Redistributions of source code must retain the above copyright notice, this
|
8
|
+
list of conditions and the following disclaimer.
|
9
|
+
|
10
|
+
* Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
this list of conditions and the following disclaimer in the documentation
|
12
|
+
and/or other materials provided with the distribution.
|
13
|
+
|
14
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
15
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
16
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
17
|
+
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
18
|
+
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
19
|
+
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
20
|
+
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
21
|
+
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
22
|
+
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
23
|
+
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
24
|
+
POSSIBILITY OF SUCH DAMAGE.
|
data/Rakefile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rake/extensiontask"
|
3
|
+
require "rspec/core/rake_task"
|
4
|
+
|
5
|
+
Rake::ExtensionTask.new "objspace_helpers" do |ext|
|
6
|
+
ext.lib_dir = "lib/objspace_helpers"
|
7
|
+
end
|
8
|
+
|
9
|
+
RSpec::Core::RakeTask.new
|
10
|
+
|
11
|
+
task spec: :compile
|
12
|
+
|
13
|
+
task default: :spec
|
14
|
+
task test: :spec
|
15
|
+
|
16
|
+
task :clean do
|
17
|
+
FileUtils.rm_rf File.join(File.dirname(__FILE__), "tmp/")
|
18
|
+
FileUtils.rm_f Dir.glob(File.join(File.dirname(__FILE__), "ext/objspace_helpers/*.o"))
|
19
|
+
FileUtils.rm_f File.join(File.dirname(__FILE__), "lib/objspace_helpers/objspace_helpers.bundle")
|
20
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
#include <objspace_info.h>
|
2
|
+
|
3
|
+
void Init_objspace_helpers(void);
|
4
|
+
|
5
|
+
static int
|
6
|
+
collect_addresses(void *vstart, void *vend, size_t stride, void *data)
|
7
|
+
{
|
8
|
+
VALUE v = (VALUE)vstart;
|
9
|
+
for (; v != (VALUE)vend; v += stride) {
|
10
|
+
if (RBASIC(v)->flags)
|
11
|
+
rb_ary_push((VALUE) data, INT2FIX((void *)v));
|
12
|
+
}
|
13
|
+
return 0;
|
14
|
+
}
|
15
|
+
|
16
|
+
static VALUE oh_dump_addresses(VALUE self)
|
17
|
+
{
|
18
|
+
VALUE ary = rb_ary_new();
|
19
|
+
rb_objspace_each_objects(collect_addresses, (void *)ary);
|
20
|
+
return ary;
|
21
|
+
}
|
22
|
+
|
23
|
+
static VALUE oh_addresses_to_info(VALUE self, VALUE ary)
|
24
|
+
{
|
25
|
+
VALUE hash, obj_addr, info_hash;
|
26
|
+
long i;
|
27
|
+
|
28
|
+
hash = rb_hash_new();
|
29
|
+
|
30
|
+
for (i = 0; i < RARRAY_LEN(ary); i += 1) {
|
31
|
+
obj_addr = rb_ary_entry(ary, i);
|
32
|
+
info_hash = rb_hash_new();
|
33
|
+
objspace_info(FIX2PTR(obj_addr), info_hash);
|
34
|
+
rb_hash_aset(hash, obj_addr, info_hash);
|
35
|
+
}
|
36
|
+
|
37
|
+
return hash;
|
38
|
+
}
|
39
|
+
|
40
|
+
static VALUE oh_address_of_obj(VALUE self, VALUE obj)
|
41
|
+
{
|
42
|
+
return PTR2FIX(obj);
|
43
|
+
}
|
44
|
+
|
45
|
+
static VALUE oh_obj_for_address(VALUE self, VALUE address)
|
46
|
+
{
|
47
|
+
return FIX2PTR(address);
|
48
|
+
}
|
49
|
+
|
50
|
+
void Init_objspace_helpers(void)
|
51
|
+
{
|
52
|
+
VALUE cObjspaceHelpers;
|
53
|
+
|
54
|
+
cObjspaceHelpers = rb_const_get(rb_cObject, rb_intern("ObjspaceHelpers"));
|
55
|
+
|
56
|
+
rb_define_singleton_method(cObjspaceHelpers, "_dump_addresses", oh_dump_addresses, 0);
|
57
|
+
rb_define_singleton_method(cObjspaceHelpers, "_addresses_to_info", oh_addresses_to_info, 1);
|
58
|
+
rb_define_singleton_method(cObjspaceHelpers, "_address_of_obj", oh_address_of_obj, 1);
|
59
|
+
rb_define_singleton_method(cObjspaceHelpers, "_obj_for_address", oh_obj_for_address, 1);
|
60
|
+
}
|
@@ -0,0 +1,175 @@
|
|
1
|
+
#include <objspace_info.h>
|
2
|
+
|
3
|
+
static inline const char *
|
4
|
+
obj_type(VALUE obj)
|
5
|
+
{
|
6
|
+
switch (BUILTIN_TYPE(obj)) {
|
7
|
+
#define CASE_TYPE(type) case T_##type: return #type; break
|
8
|
+
CASE_TYPE(NONE);
|
9
|
+
CASE_TYPE(NIL);
|
10
|
+
CASE_TYPE(OBJECT);
|
11
|
+
CASE_TYPE(CLASS);
|
12
|
+
CASE_TYPE(ICLASS);
|
13
|
+
CASE_TYPE(MODULE);
|
14
|
+
CASE_TYPE(FLOAT);
|
15
|
+
CASE_TYPE(STRING);
|
16
|
+
CASE_TYPE(REGEXP);
|
17
|
+
CASE_TYPE(ARRAY);
|
18
|
+
CASE_TYPE(HASH);
|
19
|
+
CASE_TYPE(STRUCT);
|
20
|
+
CASE_TYPE(BIGNUM);
|
21
|
+
CASE_TYPE(FILE);
|
22
|
+
CASE_TYPE(FIXNUM);
|
23
|
+
CASE_TYPE(TRUE);
|
24
|
+
CASE_TYPE(FALSE);
|
25
|
+
CASE_TYPE(DATA);
|
26
|
+
CASE_TYPE(MATCH);
|
27
|
+
CASE_TYPE(SYMBOL);
|
28
|
+
CASE_TYPE(RATIONAL);
|
29
|
+
CASE_TYPE(COMPLEX);
|
30
|
+
CASE_TYPE(UNDEF);
|
31
|
+
CASE_TYPE(NODE);
|
32
|
+
CASE_TYPE(ZOMBIE);
|
33
|
+
#undef CASE_TYPE
|
34
|
+
}
|
35
|
+
return "UNKNOWN";
|
36
|
+
}
|
37
|
+
|
38
|
+
static void
|
39
|
+
reachable_object_i(VALUE ref, void *data)
|
40
|
+
{
|
41
|
+
rb_ary_push((VALUE)data, PTR2FIX(ref));
|
42
|
+
}
|
43
|
+
|
44
|
+
#define HASH_SET(k,v) rb_hash_aset(target_hash, rb_str_new2(k), v)
|
45
|
+
#define HASH_SET_PTR(k,v) HASH_SET(k,INT2FIX((void *)v))
|
46
|
+
#define HASH_SET_INT(k,v) HASH_SET(k,INT2FIX(v))
|
47
|
+
#define HASH_SET_UINT(k,v) HASH_SET(k,UINT2NUM(v))
|
48
|
+
#define HASH_SET_ULONG(k,v) HASH_SET(k,ULONG2NUM(v))
|
49
|
+
#define HASH_SET_STR(k,v) HASH_SET(k,rb_str_new2(v))
|
50
|
+
#define HASH_SET_TRUE(k) HASH_SET(k,Qtrue)
|
51
|
+
|
52
|
+
void
|
53
|
+
objspace_info(VALUE obj, VALUE target_hash)
|
54
|
+
{
|
55
|
+
size_t memsize;
|
56
|
+
struct allocation_info *ainfo;
|
57
|
+
rb_io_t *fptr;
|
58
|
+
ID flags[RB_OBJ_GC_FLAGS_MAX];
|
59
|
+
size_t n, i;
|
60
|
+
VALUE obj_klass, references;
|
61
|
+
|
62
|
+
obj_klass = BUILTIN_TYPE(obj) == T_NODE ? 0 : RBASIC_CLASS(obj);
|
63
|
+
references = rb_ary_new();
|
64
|
+
|
65
|
+
if (obj == target_hash)
|
66
|
+
return;
|
67
|
+
|
68
|
+
HASH_SET_STR("type", obj_type(obj));
|
69
|
+
|
70
|
+
if (obj_klass)
|
71
|
+
HASH_SET_PTR("class", obj_klass);
|
72
|
+
if (rb_obj_frozen_p(obj))
|
73
|
+
HASH_SET_TRUE("frozen");
|
74
|
+
|
75
|
+
switch (BUILTIN_TYPE(obj)) {
|
76
|
+
case T_NODE:
|
77
|
+
HASH_SET_STR("node_type", ruby_node_name(nd_type(obj)));
|
78
|
+
break;
|
79
|
+
|
80
|
+
case T_STRING:
|
81
|
+
if (STR_EMBED_P(obj))
|
82
|
+
HASH_SET_TRUE("embedded");
|
83
|
+
if (STR_ASSOC_P(obj))
|
84
|
+
HASH_SET_TRUE("associated");
|
85
|
+
if (is_broken_string(obj))
|
86
|
+
HASH_SET_TRUE("broken");
|
87
|
+
if (FL_TEST(obj, RSTRING_FSTR))
|
88
|
+
HASH_SET_TRUE("fstring");
|
89
|
+
if (STR_SHARED_P(obj))
|
90
|
+
HASH_SET_TRUE("shared");
|
91
|
+
else {
|
92
|
+
HASH_SET_INT("bytesize", RSTRING_LEN(obj));
|
93
|
+
|
94
|
+
if (!STR_EMBED_P(obj) && !STR_NOCAPA_P(obj) && (long)rb_str_capacity(obj) != RSTRING_LEN(obj))
|
95
|
+
HASH_SET_INT("capacity", rb_str_capacity(obj));
|
96
|
+
|
97
|
+
if (is_ascii_string(obj))
|
98
|
+
HASH_SET("value", obj);
|
99
|
+
}
|
100
|
+
|
101
|
+
if (!ENCODING_IS_ASCII8BIT(obj))
|
102
|
+
HASH_SET_STR("encoding", rb_enc_name(rb_enc_from_index(ENCODING_GET(obj))));
|
103
|
+
|
104
|
+
break;
|
105
|
+
|
106
|
+
case T_HASH:
|
107
|
+
HASH_SET_INT("size", RHASH_SIZE(obj));
|
108
|
+
|
109
|
+
if (FL_TEST(obj, HASH_PROC_DEFAULT))
|
110
|
+
HASH_SET_PTR("default", RHASH_IFNONE(obj));
|
111
|
+
break;
|
112
|
+
|
113
|
+
case T_ARRAY:
|
114
|
+
HASH_SET_INT("length", RARRAY_LEN(obj));
|
115
|
+
|
116
|
+
if (RARRAY_LEN(obj) > 0 && FL_TEST(obj, ELTS_SHARED))
|
117
|
+
HASH_SET_TRUE("shared");
|
118
|
+
if (RARRAY_LEN(obj) > 0 && FL_TEST(obj, RARRAY_EMBED_FLAG))
|
119
|
+
HASH_SET_TRUE("embedded");
|
120
|
+
|
121
|
+
break;
|
122
|
+
|
123
|
+
case T_CLASS:
|
124
|
+
case T_MODULE:
|
125
|
+
if (obj_klass)
|
126
|
+
HASH_SET_STR("name", rb_class2name(obj));
|
127
|
+
break;
|
128
|
+
|
129
|
+
case T_DATA:
|
130
|
+
if (RTYPEDDATA_P(obj))
|
131
|
+
HASH_SET_STR("struct", RTYPEDDATA_TYPE(obj)->wrap_struct_name);
|
132
|
+
break;
|
133
|
+
|
134
|
+
case T_FLOAT:
|
135
|
+
HASH_SET("value", obj);
|
136
|
+
break;
|
137
|
+
|
138
|
+
case T_OBJECT:
|
139
|
+
HASH_SET_INT("ivars", ROBJECT_NUMIV(obj));
|
140
|
+
break;
|
141
|
+
|
142
|
+
case T_FILE:
|
143
|
+
fptr = RFILE(obj)->fptr;
|
144
|
+
if (fptr)
|
145
|
+
HASH_SET_INT("fd", fptr->fd);
|
146
|
+
break;
|
147
|
+
|
148
|
+
case T_ZOMBIE:
|
149
|
+
return;
|
150
|
+
}
|
151
|
+
|
152
|
+
rb_objspace_reachable_objects_from(obj, reachable_object_i, (void*)references);
|
153
|
+
rb_ary_delete(references, PTR2FIX(obj_klass));
|
154
|
+
HASH_SET("references", references);
|
155
|
+
|
156
|
+
if ((ainfo = objspace_lookup_allocation_info(obj))) {
|
157
|
+
HASH_SET_STR("file", ainfo->path);
|
158
|
+
HASH_SET_ULONG("line", ainfo->line);
|
159
|
+
HASH_SET_UINT("generation", ainfo->generation);
|
160
|
+
|
161
|
+
if (RTEST(ainfo->mid))
|
162
|
+
HASH_SET_STR("method", rb_id2name(SYM2ID(ainfo->mid)));
|
163
|
+
}
|
164
|
+
|
165
|
+
if ((memsize = rb_obj_memsize_of(obj)) > 0)
|
166
|
+
HASH_SET_UINT("memsize", memsize);
|
167
|
+
|
168
|
+
if ((n = rb_obj_gc_flags(obj, flags, sizeof(flags))) > 0) {
|
169
|
+
VALUE flags_hash = rb_hash_new();
|
170
|
+
for (i=0; i<n; i++) {
|
171
|
+
rb_hash_aset(flags_hash, rb_str_new2(rb_id2name(flags[i])), Qtrue);
|
172
|
+
}
|
173
|
+
HASH_SET("flags", flags_hash);
|
174
|
+
}
|
175
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
#ifndef RUBY_OBJSPACE_INFO
|
2
|
+
#define RUBY_OBJSPACE_INFO
|
3
|
+
|
4
|
+
#include <ruby.h>
|
5
|
+
#include <ruby/io.h>
|
6
|
+
|
7
|
+
#include <ruby_private/internal_defs.h>
|
8
|
+
#include <ruby_private/objspace.h>
|
9
|
+
|
10
|
+
#include <objspace_helpers.h>
|
11
|
+
|
12
|
+
void
|
13
|
+
objspace_info(VALUE obj, VALUE target_hash);
|
14
|
+
|
15
|
+
#endif
|
@@ -0,0 +1,107 @@
|
|
1
|
+
|
2
|
+
#ifndef RUBY_GC_H
|
3
|
+
#define RUBY_GC_H 1
|
4
|
+
|
5
|
+
#if defined(__x86_64__) && !defined(_ILP32) && defined(__GNUC__) && !defined(__native_client__)
|
6
|
+
#define SET_MACHINE_STACK_END(p) __asm__ __volatile__ ("movq\t%%rsp, %0" : "=r" (*(p)))
|
7
|
+
#elif defined(__i386) && defined(__GNUC__) && !defined(__native_client__)
|
8
|
+
#define SET_MACHINE_STACK_END(p) __asm__ __volatile__ ("movl\t%%esp, %0" : "=r" (*(p)))
|
9
|
+
#else
|
10
|
+
NOINLINE(void rb_gc_set_stack_end(VALUE **stack_end_p));
|
11
|
+
#define SET_MACHINE_STACK_END(p) rb_gc_set_stack_end(p)
|
12
|
+
#define USE_CONSERVATIVE_STACK_END
|
13
|
+
#endif
|
14
|
+
|
15
|
+
/* for GC debug */
|
16
|
+
|
17
|
+
#ifndef RUBY_MARK_FREE_DEBUG
|
18
|
+
#define RUBY_MARK_FREE_DEBUG 0
|
19
|
+
#endif
|
20
|
+
|
21
|
+
#if RUBY_MARK_FREE_DEBUG
|
22
|
+
extern int ruby_gc_debug_indent;
|
23
|
+
|
24
|
+
static inline void
|
25
|
+
rb_gc_debug_indent(void)
|
26
|
+
{
|
27
|
+
printf("%*s", ruby_gc_debug_indent, "");
|
28
|
+
}
|
29
|
+
|
30
|
+
static inline void
|
31
|
+
rb_gc_debug_body(const char *mode, const char *msg, int st, void *ptr)
|
32
|
+
{
|
33
|
+
if (st == 0) {
|
34
|
+
ruby_gc_debug_indent--;
|
35
|
+
}
|
36
|
+
rb_gc_debug_indent();
|
37
|
+
printf("%s: %s %s (%p)\n", mode, st ? "->" : "<-", msg, ptr);
|
38
|
+
|
39
|
+
if (st) {
|
40
|
+
ruby_gc_debug_indent++;
|
41
|
+
}
|
42
|
+
|
43
|
+
fflush(stdout);
|
44
|
+
}
|
45
|
+
|
46
|
+
#define RUBY_MARK_ENTER(msg) rb_gc_debug_body("mark", (msg), 1, ptr)
|
47
|
+
#define RUBY_MARK_LEAVE(msg) rb_gc_debug_body("mark", (msg), 0, ptr)
|
48
|
+
#define RUBY_FREE_ENTER(msg) rb_gc_debug_body("free", (msg), 1, ptr)
|
49
|
+
#define RUBY_FREE_LEAVE(msg) rb_gc_debug_body("free", (msg), 0, ptr)
|
50
|
+
#define RUBY_GC_INFO rb_gc_debug_indent(); printf
|
51
|
+
|
52
|
+
#else
|
53
|
+
#define RUBY_MARK_ENTER(msg)
|
54
|
+
#define RUBY_MARK_LEAVE(msg)
|
55
|
+
#define RUBY_FREE_ENTER(msg)
|
56
|
+
#define RUBY_FREE_LEAVE(msg)
|
57
|
+
#define RUBY_GC_INFO if(0)printf
|
58
|
+
#endif
|
59
|
+
|
60
|
+
#define RUBY_MARK_UNLESS_NULL(ptr) if(RTEST(ptr)){rb_gc_mark(ptr);}
|
61
|
+
#define RUBY_FREE_UNLESS_NULL(ptr) if(ptr){ruby_xfree(ptr);(ptr)=NULL;}
|
62
|
+
|
63
|
+
#if STACK_GROW_DIRECTION > 0
|
64
|
+
# define STACK_UPPER(x, a, b) (a)
|
65
|
+
#elif STACK_GROW_DIRECTION < 0
|
66
|
+
# define STACK_UPPER(x, a, b) (b)
|
67
|
+
#else
|
68
|
+
RUBY_EXTERN int ruby_stack_grow_direction;
|
69
|
+
int ruby_get_stack_grow_direction(volatile VALUE *addr);
|
70
|
+
# define stack_growup_p(x) ( \
|
71
|
+
(ruby_stack_grow_direction ? \
|
72
|
+
ruby_stack_grow_direction : \
|
73
|
+
ruby_get_stack_grow_direction(x)) > 0)
|
74
|
+
# define STACK_UPPER(x, a, b) (stack_growup_p(x) ? (a) : (b))
|
75
|
+
#endif
|
76
|
+
|
77
|
+
#if STACK_GROW_DIRECTION
|
78
|
+
#define STACK_GROW_DIR_DETECTION
|
79
|
+
#define STACK_DIR_UPPER(a,b) STACK_UPPER(0, (a), (b))
|
80
|
+
#else
|
81
|
+
#define STACK_GROW_DIR_DETECTION VALUE stack_grow_dir_detection
|
82
|
+
#define STACK_DIR_UPPER(a,b) STACK_UPPER(&stack_grow_dir_detection, (a), (b))
|
83
|
+
#endif
|
84
|
+
#define IS_STACK_DIR_UPPER() STACK_DIR_UPPER(1,0)
|
85
|
+
|
86
|
+
RUBY_SYMBOL_EXPORT_BEGIN
|
87
|
+
|
88
|
+
/* exports for objspace module */
|
89
|
+
size_t rb_objspace_data_type_memsize(VALUE obj);
|
90
|
+
void rb_objspace_reachable_objects_from(VALUE obj, void (func)(VALUE, void *), void *data);
|
91
|
+
void rb_objspace_reachable_objects_from_root(void (func)(const char *category, VALUE, void *), void *data);
|
92
|
+
int rb_objspace_markable_object_p(VALUE obj);
|
93
|
+
int rb_objspace_internal_object_p(VALUE obj);
|
94
|
+
int rb_objspace_marked_object_p(VALUE obj);
|
95
|
+
int rb_objspace_garbage_object_p(VALUE obj);
|
96
|
+
|
97
|
+
void rb_objspace_each_objects(
|
98
|
+
int (*callback)(void *start, void *end, size_t stride, void *data),
|
99
|
+
void *data);
|
100
|
+
|
101
|
+
void rb_objspace_each_objects_without_setup(
|
102
|
+
int (*callback)(void *, void *, size_t, void *),
|
103
|
+
void *data);
|
104
|
+
|
105
|
+
RUBY_SYMBOL_EXPORT_END
|
106
|
+
|
107
|
+
#endif /* RUBY_GC_H */
|
@@ -0,0 +1,87 @@
|
|
1
|
+
/* internal.h */
|
2
|
+
|
3
|
+
#define STR_NOEMBED FL_USER1
|
4
|
+
#define STR_SHARED FL_USER2 /* = ELTS_SHARED */
|
5
|
+
#define STR_ASSOC FL_USER3
|
6
|
+
#define STR_SHARED_P(s) FL_ALL((s), STR_NOEMBED|ELTS_SHARED)
|
7
|
+
#define STR_ASSOC_P(s) FL_ALL((s), STR_NOEMBED|STR_ASSOC)
|
8
|
+
#define STR_NOCAPA (STR_NOEMBED|ELTS_SHARED|STR_ASSOC)
|
9
|
+
#define STR_NOCAPA_P(s) (FL_TEST((s),STR_NOEMBED) && FL_ANY((s),ELTS_SHARED|STR_ASSOC))
|
10
|
+
#define STR_EMBED_P(str) (!FL_TEST((str), STR_NOEMBED))
|
11
|
+
#define is_ascii_string(str) (rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT)
|
12
|
+
#define is_broken_string(str) (rb_enc_str_coderange(str) == ENC_CODERANGE_BROKEN)
|
13
|
+
|
14
|
+
#define HASH_DELETED FL_USER1
|
15
|
+
#define HASH_PROC_DEFAULT FL_USER2
|
16
|
+
|
17
|
+
size_t rb_obj_memsize_of(VALUE);
|
18
|
+
#define RB_OBJ_GC_FLAGS_MAX 5
|
19
|
+
size_t rb_obj_gc_flags(VALUE, ID[], size_t);
|
20
|
+
void rb_gc_mark_values(long n, const VALUE *values);
|
21
|
+
|
22
|
+
|
23
|
+
/* vm_core.h */
|
24
|
+
|
25
|
+
const char *ruby_node_name(int node);
|
26
|
+
|
27
|
+
/* debug.h */
|
28
|
+
|
29
|
+
VALUE rb_tracepoint_new(VALUE target_thread_not_supported_yet, rb_event_flag_t events, void (*func)(VALUE, void *), void *data);
|
30
|
+
VALUE rb_tracepoint_enable(VALUE tpval);
|
31
|
+
VALUE rb_tracepoint_disable(VALUE tpval);
|
32
|
+
VALUE rb_tracepoint_enabled_p(VALUE tpval);
|
33
|
+
|
34
|
+
typedef struct rb_trace_arg_struct rb_trace_arg_t;
|
35
|
+
rb_trace_arg_t *rb_tracearg_from_tracepoint(VALUE tpval);
|
36
|
+
|
37
|
+
rb_event_flag_t rb_tracearg_event_flag(rb_trace_arg_t *trace_arg);
|
38
|
+
VALUE rb_tracearg_event(rb_trace_arg_t *trace_arg);
|
39
|
+
VALUE rb_tracearg_lineno(rb_trace_arg_t *trace_arg);
|
40
|
+
VALUE rb_tracearg_path(rb_trace_arg_t *trace_arg);
|
41
|
+
VALUE rb_tracearg_method_id(rb_trace_arg_t *trace_arg);
|
42
|
+
VALUE rb_tracearg_defined_class(rb_trace_arg_t *trace_arg);
|
43
|
+
VALUE rb_tracearg_binding(rb_trace_arg_t *trace_arg);
|
44
|
+
VALUE rb_tracearg_self(rb_trace_arg_t *trace_arg);
|
45
|
+
VALUE rb_tracearg_return_value(rb_trace_arg_t *trace_arg);
|
46
|
+
VALUE rb_tracearg_raised_exception(rb_trace_arg_t *trace_arg);
|
47
|
+
VALUE rb_tracearg_object(rb_trace_arg_t *trace_arg);
|
48
|
+
|
49
|
+
/* node.h */
|
50
|
+
|
51
|
+
typedef struct RNode {
|
52
|
+
VALUE flags;
|
53
|
+
VALUE nd_reserved; /* ex nd_file */
|
54
|
+
union {
|
55
|
+
struct RNode *node;
|
56
|
+
ID id;
|
57
|
+
VALUE value;
|
58
|
+
VALUE (*cfunc)(ANYARGS);
|
59
|
+
ID *tbl;
|
60
|
+
} u1;
|
61
|
+
union {
|
62
|
+
struct RNode *node;
|
63
|
+
ID id;
|
64
|
+
long argc;
|
65
|
+
VALUE value;
|
66
|
+
} u2;
|
67
|
+
union {
|
68
|
+
struct RNode *node;
|
69
|
+
ID id;
|
70
|
+
long state;
|
71
|
+
struct rb_global_entry *entry;
|
72
|
+
struct rb_args_info *args;
|
73
|
+
long cnt;
|
74
|
+
VALUE value;
|
75
|
+
} u3;
|
76
|
+
} NODE;
|
77
|
+
|
78
|
+
#define RNODE(obj) (R_CAST(RNode)(obj))
|
79
|
+
|
80
|
+
#define NODE_FL_NEWLINE (((VALUE)1)<<7)
|
81
|
+
#define NODE_FL_CREF_PUSHED_BY_EVAL (((VALUE)1)<<15)
|
82
|
+
#define NODE_FL_CREF_OMOD_SHARED (((VALUE)1)<<16)
|
83
|
+
|
84
|
+
#define NODE_TYPESHIFT 8
|
85
|
+
#define NODE_TYPEMASK (((VALUE)0x7f)<<NODE_TYPESHIFT)
|
86
|
+
|
87
|
+
#define nd_type(n) ((int) (((RNODE(n))->flags & NODE_TYPEMASK)>>NODE_TYPESHIFT))
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/* object_tracing.c */
|
2
|
+
struct allocation_info {
|
3
|
+
/* all of information don't need marking. */
|
4
|
+
int living;
|
5
|
+
VALUE flags;
|
6
|
+
VALUE klass;
|
7
|
+
|
8
|
+
/* allocation info */
|
9
|
+
const char *path;
|
10
|
+
unsigned long line;
|
11
|
+
const char *class_path;
|
12
|
+
VALUE mid;
|
13
|
+
size_t generation;
|
14
|
+
};
|
15
|
+
extern struct allocation_info *objspace_lookup_allocation_info(VALUE obj);
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class ObjspaceHelpers
|
2
|
+
def self.dump_all_addresses
|
3
|
+
_dump_addresses
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.info_for_address(addresses)
|
7
|
+
_addresses_to_info(addresses)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.info_for_obj(obj)
|
11
|
+
_addresses_to_info([address_of(obj)]).values.first
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.obj_for(address)
|
15
|
+
_obj_for_address(address)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.address_of(obj)
|
19
|
+
_address_of_obj(obj)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.diff(&block)
|
23
|
+
objs_before = dump_all_addresses
|
24
|
+
block.call
|
25
|
+
objs_after = dump_all_addresses
|
26
|
+
objs_after - objs_before - [address_of(objs_after)]
|
27
|
+
end
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: objspace_helpers
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Lukas Fittl
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-11-24 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake-compiler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: json
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.8'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.8'
|
55
|
+
description: Diff the heap to find leaks & get other ObjectSpace info more easily.
|
56
|
+
email: lukas@fittl.com
|
57
|
+
executables: []
|
58
|
+
extensions:
|
59
|
+
- ext/objspace_helpers/extconf.rb
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- LICENSE
|
63
|
+
- Rakefile
|
64
|
+
- ext/objspace_helpers/extconf.rb
|
65
|
+
- ext/objspace_helpers/objspace_helpers.c
|
66
|
+
- ext/objspace_helpers/objspace_helpers.h
|
67
|
+
- ext/objspace_helpers/objspace_info.c
|
68
|
+
- ext/objspace_helpers/objspace_info.h
|
69
|
+
- ext/objspace_helpers/ruby_private/gc.h
|
70
|
+
- ext/objspace_helpers/ruby_private/internal_defs.h
|
71
|
+
- ext/objspace_helpers/ruby_private/objspace.h
|
72
|
+
- lib/objspace_helpers.rb
|
73
|
+
- lib/objspace_helpers/helpers.rb
|
74
|
+
- lib/objspace_helpers/version.rb
|
75
|
+
homepage: http://github.com/lfittl/objspace_helpers
|
76
|
+
licenses:
|
77
|
+
- BSD-2-Clause
|
78
|
+
metadata: {}
|
79
|
+
post_install_message:
|
80
|
+
rdoc_options: []
|
81
|
+
require_paths:
|
82
|
+
- lib
|
83
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
requirements: []
|
94
|
+
rubyforge_project:
|
95
|
+
rubygems_version: 2.2.2
|
96
|
+
signing_key:
|
97
|
+
specification_version: 4
|
98
|
+
summary: Helper library to work with ObjectSpace in MRI Ruby 2.1+
|
99
|
+
test_files: []
|