objspace_helpers 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|