utilrb 1.6.5 → 1.6.6
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.
- data/Manifest.txt +2 -0
- data/ext/proc.cc +38 -0
- data/lib/utilrb/common.rb +1 -1
- data/lib/utilrb/configsearch/configuration_finder.rb +2 -2
- data/lib/utilrb/ruby_object_graph.rb +235 -0
- metadata +19 -17
data/Manifest.txt
CHANGED
@@ -7,6 +7,7 @@ Rakefile
|
|
7
7
|
bm/allocation.rb
|
8
8
|
bm/speed.rb
|
9
9
|
ext/extconf.rb
|
10
|
+
ext/proc.cc
|
10
11
|
ext/ruby_internals-1.8.h
|
11
12
|
ext/ruby_internals-1.9.h
|
12
13
|
ext/swap.cc
|
@@ -75,6 +76,7 @@ lib/utilrb/object/singleton_class.rb
|
|
75
76
|
lib/utilrb/objectstats.rb
|
76
77
|
lib/utilrb/pkgconfig.rb
|
77
78
|
lib/utilrb/rake_common.rb
|
79
|
+
lib/utilrb/ruby_object_graph.rb
|
78
80
|
lib/utilrb/set.rb
|
79
81
|
lib/utilrb/set/to_s.rb
|
80
82
|
lib/utilrb/socket/tcp_server.rb
|
data/ext/proc.cc
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
#ifdef HAS_RUBY_SOURCE
|
2
|
+
extern "C" {
|
3
|
+
#include "/usr/include/ruby-1.9.1/ruby-1.9.3-p0/vm_core.h"
|
4
|
+
}
|
5
|
+
|
6
|
+
static VALUE env_references(VALUE rbenv)
|
7
|
+
{
|
8
|
+
rb_env_t* env;
|
9
|
+
|
10
|
+
VALUE result = rb_ary_new();
|
11
|
+
GetEnvPtr(rbenv, env);
|
12
|
+
if (env->env)
|
13
|
+
{
|
14
|
+
for (int i = 0; i < env->env_size; ++i)
|
15
|
+
rb_ary_push(result, rb_obj_id(env->env[i]));
|
16
|
+
}
|
17
|
+
return result;
|
18
|
+
}
|
19
|
+
|
20
|
+
static VALUE proc_references(VALUE rbproc)
|
21
|
+
{
|
22
|
+
rb_proc_t* proc;
|
23
|
+
GetProcPtr(rbproc, proc);
|
24
|
+
|
25
|
+
if (!NIL_P(proc->envval))
|
26
|
+
return env_references(proc->envval);
|
27
|
+
return rb_ary_new();
|
28
|
+
}
|
29
|
+
#else
|
30
|
+
#warning "RUBY_SOURCE_DIR is not set, Proc#references will not be available"
|
31
|
+
#endif
|
32
|
+
|
33
|
+
extern "C" void Init_proc()
|
34
|
+
{
|
35
|
+
#ifdef HAS_RUBY_SOURCE
|
36
|
+
rb_define_method(rb_cProc, "references", RUBY_METHOD_FUNC(proc_references), 0);
|
37
|
+
#endif
|
38
|
+
}
|
data/lib/utilrb/common.rb
CHANGED
@@ -10,8 +10,8 @@ module Utilrb
|
|
10
10
|
#
|
11
11
|
# Returns the path to the file on success, otherwise nil
|
12
12
|
def self.findWithEnv(filename, pkg_name, environment_search_path)
|
13
|
-
|
14
|
-
|
13
|
+
env_var = ENV[environment_search_path]
|
14
|
+
if env_var
|
15
15
|
# Extract search path from environment variable
|
16
16
|
configuration_path = Array.new
|
17
17
|
env_var.split(':').each do | path |
|
@@ -0,0 +1,235 @@
|
|
1
|
+
module Utilrb
|
2
|
+
begin
|
3
|
+
require 'roby/graph'
|
4
|
+
has_roby_graph = true
|
5
|
+
rescue LoadError
|
6
|
+
has_roby_graph = false
|
7
|
+
end
|
8
|
+
|
9
|
+
if has_roby_graph
|
10
|
+
class RubyObjectGraph
|
11
|
+
attr_reader :graph
|
12
|
+
attr_reader :references
|
13
|
+
|
14
|
+
def self.snapshot
|
15
|
+
# Doing any Ruby code that do not modify the heap is impossible. List
|
16
|
+
# all existing objects once, and only then do the processing.
|
17
|
+
# +live_objects+ will be referenced in itself, but we are going to
|
18
|
+
# remove it later
|
19
|
+
GC.disable
|
20
|
+
live_objects = []
|
21
|
+
ObjectSpace.each_object do |obj|
|
22
|
+
if obj != live_objects
|
23
|
+
live_objects << obj
|
24
|
+
end
|
25
|
+
end
|
26
|
+
GC.enable
|
27
|
+
end
|
28
|
+
|
29
|
+
def initialize
|
30
|
+
@graph = BGL::Graph.new
|
31
|
+
@references = Hash.new
|
32
|
+
end
|
33
|
+
|
34
|
+
class ObjectRef
|
35
|
+
attr_reader :obj
|
36
|
+
def initialize(obj)
|
37
|
+
@obj = obj
|
38
|
+
end
|
39
|
+
include BGL::Vertex
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_and_add_reference(obj_ref, var, desc)
|
43
|
+
var_ref = references[var.object_id]
|
44
|
+
if graph.include?(var_ref)
|
45
|
+
add_reference(obj_ref, var_ref, desc)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def add_reference(obj_ref, var_ref, desc)
|
50
|
+
if graph.linked?(obj_ref, var_ref)
|
51
|
+
obj_ref[var_ref, graph] << desc
|
52
|
+
else
|
53
|
+
graph.link(obj_ref, var_ref, [desc].to_set)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def register_references_to(klass, orig_options = Hash.new)
|
58
|
+
options = Kernel.validate_options orig_options,
|
59
|
+
:roots => nil
|
60
|
+
roots = options[:roots]
|
61
|
+
|
62
|
+
live_objects = RubyObjectGraph.snapshot
|
63
|
+
|
64
|
+
# Create a single ObjectRef per (interesting) live object, so that we
|
65
|
+
# can use a BGL::Graph to represent the reference graph. This will be
|
66
|
+
# what we are going to access later on. Use object IDs since we really
|
67
|
+
# want to refer to objects and not use eql? comparisons
|
68
|
+
desired_seeds = []
|
69
|
+
excludes = [live_objects, self, orig_options, options, roots].to_value_set
|
70
|
+
live_objects.delete_if do |obj|
|
71
|
+
if excludes.include?(obj)
|
72
|
+
true
|
73
|
+
else
|
74
|
+
references[obj.object_id] ||= ObjectRef.new(obj)
|
75
|
+
if obj.kind_of?(klass)
|
76
|
+
desired_seeds << obj.object_id
|
77
|
+
end
|
78
|
+
false
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
desired_seeds.each do |obj_id|
|
83
|
+
graph.insert(references[obj_id])
|
84
|
+
end
|
85
|
+
ignored_enumeration = Hash.new
|
86
|
+
|
87
|
+
loop do
|
88
|
+
old_graph_size = graph.size
|
89
|
+
live_objects.each do |obj|
|
90
|
+
obj_ref = references[obj.object_id]
|
91
|
+
|
92
|
+
test_and_add_reference(obj_ref, obj.class, "class")
|
93
|
+
|
94
|
+
for var_name in obj.instance_variables
|
95
|
+
var = obj.instance_variable_get(var_name)
|
96
|
+
test_and_add_reference(obj_ref, var, var_name.to_s)
|
97
|
+
end
|
98
|
+
|
99
|
+
case obj
|
100
|
+
when Array, ValueSet
|
101
|
+
for var in obj
|
102
|
+
test_and_add_reference(obj_ref, var, "ValueSet[]")
|
103
|
+
end
|
104
|
+
when BGL::Graph
|
105
|
+
obj.each_vertex do
|
106
|
+
test_and_add_reference(obj_ref, var, "Vertex[]")
|
107
|
+
end
|
108
|
+
obj.each_edge do |_, _, info|
|
109
|
+
test_and_add_reference(obj_ref, info, "Edge[]")
|
110
|
+
end
|
111
|
+
when Hash
|
112
|
+
for var in obj
|
113
|
+
2.times do |i|
|
114
|
+
test_and_add_reference(obj_ref, var[i], "Hash[]")
|
115
|
+
end
|
116
|
+
end
|
117
|
+
when Proc
|
118
|
+
if obj.respond_to?(:references)
|
119
|
+
for var in obj.references
|
120
|
+
begin
|
121
|
+
test_and_add_reference(obj_ref, ObjectSpace._id2ref(var), "Proc")
|
122
|
+
rescue RangeError
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
else
|
127
|
+
if obj.respond_to?(:each)
|
128
|
+
if obj.kind_of?(Module) || obj.kind_of?(Class)
|
129
|
+
if !ignored_enumeration[obj]
|
130
|
+
ignored_enumeration[obj] = true
|
131
|
+
puts "ignoring enumerator class/module #{obj}"
|
132
|
+
end
|
133
|
+
else
|
134
|
+
if !ignored_enumeration[obj.class]
|
135
|
+
ignored_enumeration[obj.class] = true
|
136
|
+
puts "ignoring enumerator object #{obj.class}"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
if old_graph_size == graph.size
|
143
|
+
break
|
144
|
+
end
|
145
|
+
end
|
146
|
+
return graph
|
147
|
+
end
|
148
|
+
|
149
|
+
def collapse(*klasses)
|
150
|
+
vertices = graph.vertices.dup
|
151
|
+
vertices.each do |v|
|
152
|
+
case v.obj
|
153
|
+
when *klasses
|
154
|
+
next if v.root?(graph) || v.leaf?(graph)
|
155
|
+
|
156
|
+
v.each_parent_vertex(graph) do |parent|
|
157
|
+
all_parent_info = parent[v, graph]
|
158
|
+
v.each_child_vertex(graph) do |child|
|
159
|
+
all_child_info = v[child, graph]
|
160
|
+
all_parent_info.each do |parent_info|
|
161
|
+
all_child_info.each do |child_info|
|
162
|
+
add_reference(parent, child, parent_info + "." + child_info)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
graph.remove(v)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def to_dot
|
173
|
+
if !roots
|
174
|
+
roots = graph.vertices.find_all do |v|
|
175
|
+
v.root?(graph)
|
176
|
+
end.to_value_set
|
177
|
+
else
|
178
|
+
roots = roots.to_value_set
|
179
|
+
end
|
180
|
+
|
181
|
+
io = StringIO.new("")
|
182
|
+
|
183
|
+
all_seen = ValueSet.new
|
184
|
+
io.puts "digraph {"
|
185
|
+
roots.each do |obj_ref|
|
186
|
+
seen = ValueSet.new
|
187
|
+
graph.each_dfs(obj_ref, BGL::Graph::ALL) do |from_ref, to_ref, all_info, kind|
|
188
|
+
info = all_info.to_a.join(",")
|
189
|
+
|
190
|
+
if all_seen.include?(from_ref)
|
191
|
+
graph.prune
|
192
|
+
else
|
193
|
+
from_id = from_ref.obj.object_id
|
194
|
+
to_id = to_ref.obj.object_id
|
195
|
+
io.puts "obj#{from_id} -> obj#{to_id} [label=\"#{info}\"]"
|
196
|
+
end
|
197
|
+
seen << from_ref << to_ref
|
198
|
+
end
|
199
|
+
|
200
|
+
seen.each do |obj_ref|
|
201
|
+
if !all_seen.include?(obj_ref)
|
202
|
+
obj = obj_ref.obj
|
203
|
+
obj_id = obj_ref.obj.object_id
|
204
|
+
str =
|
205
|
+
if obj.respond_to?(:each)
|
206
|
+
"#{obj.class}"
|
207
|
+
else
|
208
|
+
obj.to_s
|
209
|
+
end
|
210
|
+
|
211
|
+
color =
|
212
|
+
if obj.kind_of?(Roby::EventGenerator)
|
213
|
+
"cyan"
|
214
|
+
elsif obj.kind_of?(Roby::Task)
|
215
|
+
"blue"
|
216
|
+
elsif obj.kind_of?(BGL::Graph)
|
217
|
+
"magenta"
|
218
|
+
elsif obj.kind_of?(Hash) || obj.kind_of?(Array) || obj.kind_of?(ValueSet)
|
219
|
+
"green"
|
220
|
+
else
|
221
|
+
"black"
|
222
|
+
end
|
223
|
+
|
224
|
+
io.puts "obj#{obj_id} [label=\"#{str}\",color=#{color}];"
|
225
|
+
end
|
226
|
+
end
|
227
|
+
all_seen.merge(seen)
|
228
|
+
end
|
229
|
+
io.puts "}"
|
230
|
+
io.string
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: utilrb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 3
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 6
|
9
|
-
-
|
10
|
-
version: 1.6.
|
9
|
+
- 6
|
10
|
+
version: 1.6.6
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Sylvain Joyeux
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-
|
18
|
+
date: 2012-09-18 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: facets
|
@@ -121,6 +121,7 @@ files:
|
|
121
121
|
- bm/allocation.rb
|
122
122
|
- bm/speed.rb
|
123
123
|
- ext/extconf.rb
|
124
|
+
- ext/proc.cc
|
124
125
|
- ext/ruby_internals-1.8.h
|
125
126
|
- ext/ruby_internals-1.9.h
|
126
127
|
- ext/swap.cc
|
@@ -189,6 +190,7 @@ files:
|
|
189
190
|
- lib/utilrb/objectstats.rb
|
190
191
|
- lib/utilrb/pkgconfig.rb
|
191
192
|
- lib/utilrb/rake_common.rb
|
193
|
+
- lib/utilrb/ruby_object_graph.rb
|
192
194
|
- lib/utilrb/set.rb
|
193
195
|
- lib/utilrb/set/to_s.rb
|
194
196
|
- lib/utilrb/socket/tcp_server.rb
|
@@ -260,22 +262,22 @@ signing_key:
|
|
260
262
|
specification_version: 3
|
261
263
|
summary: Yet another Ruby toolkit
|
262
264
|
test_files:
|
263
|
-
- test/
|
265
|
+
- test/test_weakref.rb
|
264
266
|
- test/test_unbound_method.rb
|
265
|
-
- test/
|
267
|
+
- test/test_enumerable.rb
|
266
268
|
- test/test_exception.rb
|
267
|
-
- test/test_config.rb
|
268
|
-
- test/test_time.rb
|
269
|
-
- test/test_logger.rb
|
270
|
-
- test/test_module.rb
|
271
269
|
- test/test_objectstats.rb
|
272
|
-
- test/test_enumerable.rb
|
273
|
-
- test/test_gc.rb
|
274
|
-
- test/test_misc.rb
|
275
|
-
- test/test_object.rb
|
276
|
-
- test/test_array.rb
|
277
270
|
- test/test_dir.rb
|
278
|
-
- test/
|
279
|
-
- test/
|
271
|
+
- test/test_time.rb
|
272
|
+
- test/test_misc.rb
|
280
273
|
- test/test_set.rb
|
274
|
+
- test/test_config.rb
|
275
|
+
- test/test_logger.rb
|
276
|
+
- test/test_proc.rb
|
277
|
+
- test/test_hash.rb
|
278
|
+
- test/test_array.rb
|
279
|
+
- test/test_object.rb
|
280
|
+
- test/test_module.rb
|
281
|
+
- test/test_kernel.rb
|
281
282
|
- test/test_pkgconfig.rb
|
283
|
+
- test/test_gc.rb
|