rb-threadframe 0.37 → 0.38

Sign up to get free protection for your applications and to get access to all the features.
data/NEWS CHANGED
@@ -1,3 +1,8 @@
1
+ March 15, 2011 (0.38) Ron Frankel Release
2
+ - Add RubyVM::ThreadFrame.prev (same as RubyVM::ThreadFrame.current.prev)
3
+ - Allow access to a C method type
4
+ - Method extensions now included on UnboundMethods as well
5
+
1
6
  Feb 1, 2011 (0.37)
2
7
  - 1.9.2 patches:
3
8
  * Mark VM Instruction sequences for no garbage collection if they are
data/Rakefile CHANGED
@@ -20,14 +20,14 @@ task :gem=>:gemspec do
20
20
  Dir.chdir(ROOT_DIR) do
21
21
  sh "gem build .gemspec"
22
22
  FileUtils.mkdir_p 'pkg'
23
- FileUtils.mv "#{gemspec.name}-#{gemspec.version}.gem", 'pkg'
23
+ FileUtils.mv("#{gemspec.file_name}", "pkg/")
24
24
  end
25
25
  end
26
26
 
27
27
  desc "Install the gem locally"
28
28
  task :install => :gem do
29
29
  Dir.chdir(ROOT_DIR) do
30
- sh %{gem install --local pkg/#{gemspec.name}-#{gemspec.version}}
30
+ sh %{gem install --local pkg/#{gemspec.file_name}}
31
31
  end
32
32
  end
33
33
 
@@ -73,7 +73,7 @@ Rake::TestTask.new(:'test:unit') do |t|
73
73
  t.libs << './ext'
74
74
  t.test_files = FileList['test/unit/**/*.rb']
75
75
  # t.pattern = 'test/**/*test-*.rb' # instead of above
76
- t.verbose = true
76
+ t.options = '--verbose' if $VERBOSE
77
77
  end
78
78
  task :'test:unit' => [:ext]
79
79
 
@@ -49,9 +49,10 @@ extern rb_iseq_t *rb_method_get_iseq(VALUE method);
49
49
 
50
50
  #if 0 /* The following is to fake out rdoc, until I find a better fix. */
51
51
  /*
52
- * Additions to the RubyVM::Method class
52
+ * Additions to the RubyVM::Method and RubyVM::UnboundMethod class
53
53
  */
54
54
  VALUE rb_cIseq = rb_define_class("Method", ...)
55
+ VALUE rb_cIseq = rb_define_class("UnboundMethod", ...)
55
56
  #endif
56
57
  /*
57
58
  * call-seq:
@@ -70,6 +71,78 @@ method_iseq(VALUE self)
70
71
  return rb_iseq;
71
72
  }
72
73
 
74
+ static void null_gc_proc(void *ptr) { }
75
+
76
+ static size_t null_gc_memsize(const void *ptr) { }
77
+
78
+
79
+ static const rb_data_type_t method_data_type = {
80
+ "method",
81
+ null_gc_proc,
82
+ null_gc_proc,
83
+ null_gc_memsize,
84
+ };
85
+
86
+ static inline rb_method_definition_t *
87
+ method_get_def(VALUE method)
88
+ {
89
+ /* FIXME: use
90
+ struct METHOD *data;
91
+ TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
92
+ */
93
+ struct METHOD *data = (struct METHOD *)DATA_PTR(method);
94
+ return data->me.def;
95
+ }
96
+
97
+ /*
98
+ * call-seq:
99
+ * Method#type -> String
100
+ *
101
+ * Returns the Method object.
102
+ */
103
+ VALUE
104
+ method_type(VALUE self)
105
+ {
106
+ rb_method_definition_t *def = method_get_def(self);
107
+ const char *type_str;
108
+ switch (def->type) {
109
+ case VM_METHOD_TYPE_ISEQ:
110
+ type_str = "instruction sequence";
111
+ break;
112
+ case VM_METHOD_TYPE_CFUNC:
113
+ type_str = "C function";
114
+ break;
115
+ case VM_METHOD_TYPE_ATTRSET:
116
+ type_str = "attrset";
117
+ break;
118
+ case VM_METHOD_TYPE_IVAR:
119
+ type_str = "ivar";
120
+ break;
121
+ case VM_METHOD_TYPE_BMETHOD:
122
+ type_str = "bmethod";
123
+ break;
124
+ case VM_METHOD_TYPE_ZSUPER:
125
+ type_str = "zsuper";
126
+ break;
127
+ case VM_METHOD_TYPE_UNDEF:
128
+ type_str = "undefined";
129
+ break;
130
+ case VM_METHOD_TYPE_NOTIMPLEMENTED:
131
+ type_str = "not implemented";
132
+ break;
133
+ case VM_METHOD_TYPE_OPTIMIZED: /* Kernel#send, Proc#call, etc */
134
+ type_str = "optimized";
135
+ break;
136
+ case VM_METHOD_TYPE_MISSING: /* wrapper for method_missing(id) */
137
+ type_str = "type missing";
138
+ break;
139
+ default:
140
+ type_str = "unknown";
141
+ break;
142
+ }
143
+ return rb_str_new2(type_str);
144
+ }
145
+
73
146
  /*
74
147
  * call-seq:
75
148
  * Method#alias_count -> Fixnum
@@ -102,7 +175,12 @@ Init_proc_extra(void)
102
175
  rb_define_method(rb_cProc, "iseq", proc_iseq, 0);
103
176
 
104
177
  /* Additions to Method */
105
- rb_define_method(rb_cMethod, "iseq", method_iseq, 0);
106
178
  rb_define_method(rb_cMethod, "alias_count", method_alias_count, 0);
179
+ rb_define_method(rb_cMethod, "iseq", method_iseq, 0);
107
180
  rb_define_method(rb_cMethod, "original_id", method_original_id, 0);
181
+ rb_define_method(rb_cMethod, "type", method_type, 0);
182
+
183
+ rb_define_method(rb_cUnboundMethod, "alias_count", method_alias_count, 0);
184
+ rb_define_method(rb_cUnboundMethod, "original_id", method_original_id, 0);
185
+ rb_define_method(rb_cUnboundMethod, "type", method_type, 0);
108
186
  }
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  /* What release we got? */
9
- #define THREADFRAME_VERSION "0.37"
9
+ #define THREADFRAME_VERSION "0.38"
10
10
 
11
11
  #include <string.h>
12
12
  #include "../include/vm_core_mini.h" /* Pulls in ruby.h and node.h */
@@ -114,7 +114,11 @@ tf_free(void *ptr)
114
114
  thread_frame_t *tf;
115
115
  if (ptr) {
116
116
  tf = ptr;
117
- if (RUBY_VM_NORMAL_ISEQ_P(tf->cfp->iseq))
117
+ /* All valid frame types have 0x1 set so we will use this.
118
+ Warning: this is an undocumented assumption which may someday
119
+ be wrong. */
120
+ if (tf->cfp && ((tf->cfp->flag & 0x1) == 0) &&
121
+ RUBY_VM_NORMAL_ISEQ_P(tf->cfp->iseq))
118
122
  tf->cfp->iseq->in_use--;
119
123
  xfree(ptr);
120
124
  }
@@ -812,44 +816,93 @@ thread_frame_s_current(VALUE klass)
812
816
  /*
813
817
  * call-seq:
814
818
  * RubyVM::ThreadFrame::prev(thread) -> threadframe_object
815
- * RubyVM::ThreadFrame::prev(thread, n) -> threadframe_object
819
+ * RubyVM::ThreadFrame::prev(thread, n) -> threadframe_object
820
+ * RubyVM::ThreadFrame::prev -> threadframe_object
821
+ * RubyVM::ThreadFrame::prev(n) -> threadframe_object
822
+ *
823
+ * In the first form, we return a RubyVM::ThreadFrame prior to the
824
+ * Thread object passed. That is we go back one frame from the
825
+ * current frfame.
826
+ *
827
+ * In the second form we try to go back that many thread frames.
828
+ *
829
+ * In the the third form, the current thread is assumed, and like the
830
+ * first form we go back one frame.
831
+ *
832
+ * The fourth form, like the third form, we assume the current
833
+ * thread. And like the first form we go back we try to back a
834
+ * FixNum number of entries.
835
+ *
836
+ * When count +n+ is given 1 is synonymous with the previous frame
837
+ * and 0 is invalid. If the +n+ is negative, we count from the bottom
838
+ * of the frame stack.
839
+ *
840
+ * In all cases we return a RubyVM::ThreadFrame or nil if we can't
841
+ * go back (or forward for a negative +n+) that many frames.
816
842
  *
817
- * Returns a RubyVM::ThreadFrame for the frame prior to the
818
- * Thread object passed or nil if there is none. The default value for n
819
- * is 1. 0 just returns the object passed.
820
- * Negative counts or counts exceeding the stack will return nil.
821
843
  */
822
844
  static VALUE
823
845
  thread_frame_s_prev(int argc, VALUE *argv, VALUE klass)
824
846
  {
825
- VALUE thval;
826
- VALUE nv;
827
- int n;
828
-
829
- rb_scan_args(argc, argv, "11", &thval, &nv);
830
-
831
- if (Qfalse == rb_obj_is_kind_of(thval, rb_cThread))
832
- rb_raise(rb_eTypeError,
833
- "ThreadFrame object needed for first argument");
834
-
835
- GET_THREAD_PTR ;
847
+ VALUE first_val;
848
+ VALUE second_val;
849
+ VALUE thval = Qnil;
850
+ int prev_count = 0;
851
+ rb_thread_t *th = NULL;
852
+
853
+ /* Such complicated options processing. But we do want this
854
+ routine to be convenient. */
855
+ rb_scan_args(argc, argv, "02", &first_val, &second_val);
856
+ switch (argc) {
857
+ case 0:
858
+ th = ruby_current_thread;
859
+ /* Do'nt count the RubyVM::ThreadFrame.prev call */
860
+ prev_count = 2;
861
+ break;
862
+ case 1:
863
+ if (FIXNUM_P(first_val)) {
864
+ prev_count = FIX2INT(first_val);
865
+ if (prev_count > 0) prev_count++ ;
866
+ th = ruby_current_thread;
867
+ } else
868
+ if (Qtrue == rb_obj_is_kind_of(first_val, rb_cThread)) {
869
+ GetThreadPtr(first_val, th);
870
+ /* Don't count the RubyVM::ThreadFrame.prev call */
871
+ prev_count = 1;
872
+ } else {
873
+ rb_raise(rb_eTypeError,
874
+ "FixNum or ThreadFrame object expected for first argument");
875
+ }
876
+ break;
877
+ case 2:
878
+ if (Qtrue == rb_obj_is_kind_of(first_val, rb_cThread)) {
879
+ GetThreadPtr(first_val, th);
880
+ } else {
881
+ rb_raise(rb_eTypeError,
882
+ "ThreadFrame object expected for first argument");
883
+ }
884
+ if (FIXNUM_P(second_val)) {
885
+ prev_count = FIX2INT(second_val);
886
+ } else
887
+ rb_raise(rb_eTypeError,
888
+ "FixNum previous count expected for second argument");
889
+ break;
890
+ default:
891
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..2)", argc);
892
+ }
836
893
 
837
- if (Qnil == nv)
838
- n = 1;
839
- else if (!FIXNUM_P(nv)) {
840
- rb_raise(rb_eTypeError, "Fixnum needed for second argument");
841
- } else
842
- n = FIX2INT(nv);
894
+ if (0 == prev_count) {
895
+ rb_raise(rb_eArgError,
896
+ "previous count can not be 0. Use current instead of prev");
897
+ }
843
898
 
844
- if (n == 0) {
845
- return thread_frame_s_current(klass);
846
- } else if (n < 0) {
899
+ if (0 > prev_count) {
847
900
  int stack_size = thread_frame_stack_size_internal(th->cfp, th);
848
- if (-n > stack_size) return Qnil;
849
- n = stack_size + n;
901
+ if (-prev_count > stack_size) return Qnil;
902
+ prev_count = stack_size + prev_count;
850
903
  }
851
904
 
852
- return thread_frame_prev_internal(th->cfp, th, n);
905
+ return thread_frame_prev_internal(th->cfp, th, prev_count);
853
906
  }
854
907
 
855
908
  /*
@@ -0,0 +1,4 @@
1
+ VALUE thread_frame_sp(VALUE klass, VALUE index) ;
2
+ VALUE thread_frame_prev(int argc, VALUE *argv, VALUE klass);
3
+
4
+
@@ -23,7 +23,7 @@ class TestARGC < Test::Unit::TestCase
23
23
  all_events = []
24
24
  eval <<-EOF.gsub(/^.*?: /, "")
25
25
  1: set_trace_func(Proc.new { |event, file, lineno, mid, binding, klass|
26
- 2: tf = RubyVM::ThreadFrame.current.prev(1)
26
+ 2: tf = RubyVM::ThreadFrame.prev
27
27
  3: all_events << [tf.argc, tf.arity, tf.type, mid]
28
28
  4: if :basename == mid
29
29
  5: events << [tf.argc, tf.arity, tf.type, mid]
@@ -21,18 +21,26 @@ class TestThread < Test::Unit::TestCase
21
21
 
22
22
  def test_prev
23
23
 
24
- assert RubyVM::ThreadFrame::prev(Thread::current, 0)
25
- assert(RubyVM::ThreadFrame::prev(Thread::current, 2),
26
- 'There should be at least two prior frames')
24
+ assert RubyVM::ThreadFrame::prev(Thread::current, 1),
25
+ 'should allow 2-arg prev'
26
+ assert RubyVM::ThreadFrame::prev(Thread::current),
27
+ 'should allow 1-arg thread prev'
28
+ assert(RubyVM::ThreadFrame::prev(2),
29
+ 'There should be at least two prior frames in single Fixnum prev')
27
30
 
28
31
  top_frame = RubyVM::ThreadFrame::prev(Thread::current, -1)
29
- assert(top_frame, 'Should give back the top frame')
32
+ assert(top_frame, 'Should give back the top frame for two arg and -1')
33
+ assert_equal('TOP', top_frame.type,
34
+ 'The type of the top frame should be "TOP"')
35
+
36
+ top_frame = RubyVM::ThreadFrame::prev(-1)
37
+ assert(top_frame, 'Should give back the top frame for one arg and -1')
30
38
  assert_equal('TOP', top_frame.type,
31
39
  'The type of the top frame should be "TOP"')
32
40
 
33
41
  assert_equal(nil, RubyVM::ThreadFrame::prev(Thread::current, 1000))
34
42
 
35
- tf = RubyVM::ThreadFrame::current.prev
43
+ tf = RubyVM::ThreadFrame.prev
36
44
 
37
45
  assert tf.prev(2)
38
46
  assert_equal(tf, tf.prev(0),
@@ -43,6 +51,9 @@ class TestThread < Test::Unit::TestCase
43
51
  assert_raises TypeError do
44
52
  tf.prev('a')
45
53
  end
54
+ assert_raises ArgumentError do
55
+ tf.prev(RubyVM::ThreadFrame::current, 1, 'bad_arg')
56
+ end
46
57
  assert_raises TypeError do
47
58
  RubyVM::ThreadFrame::prev([1])
48
59
  end
@@ -19,5 +19,9 @@ class TestProcAndMethod < Test::Unit::TestCase
19
19
  assert_equal(3, m.alias_count)
20
20
  assert_equal(4, self.method(:two).alias_count)
21
21
  assert_equal(:test_method_extra, self.method(:two).original_id)
22
+ assert_equal("instruction sequence", method(:test_method_extra).type)
23
+ assert_equal("C function", File.method(:basename).type)
24
+ # Array.map is an unbound method
25
+ assert_equal("C function", Array.instance_method(:map).type)
22
26
  end
23
27
  end
@@ -45,10 +45,13 @@ class TestSetTraceFunc < Test::Unit::TestCase
45
45
  5: set_trace_func(nil)
46
46
  EOF
47
47
 
48
- expected = [[4, 'line', __method__, self.class],
48
+ expected = [
49
+ [4, 'line', __method__, self.class],
50
+ [4, 'send', __method__, self.class],
49
51
  [4, "c-call", :+, Fixnum],
50
52
  [4, "c-return", :+, Fixnum],
51
53
  [5, "line", __method__, self.class],
54
+ [5, "send", __method__, self.class],
52
55
  [5, "c-call", :set_trace_func, Kernel]]
53
56
  checkit(@events, expected)
54
57
  end
@@ -65,17 +68,25 @@ class TestSetTraceFunc < Test::Unit::TestCase
65
68
  8: set_trace_func(nil)
66
69
  EOF
67
70
 
68
- expected = [[4, 'line', __method__, self.class],
69
- [4, 'c-call', :method_added, Module],
70
- [4, 'c-return', :method_added, Module],
71
- [7, 'line', __method__, self.class],
72
- [4, 'call', :add, self.class],
73
- [5, 'line', :add, self.class],
74
- [5, 'c-call', :+, Fixnum],
75
- [5, 'c-return', :+, Fixnum],
76
- [6, 'return', :add, self.class],
77
- [8, 'line', __method__, self.class],
78
- [8, 'c-call', :set_trace_func, Kernel]]
71
+ expected =
72
+ [
73
+ [4, 'line', __method__, self.class],
74
+ [4, 'send', __method__, self.class],
75
+ [4, 'c-call', :method_added, Module],
76
+ [4, 'c-return', :method_added, Module],
77
+ [7, 'line', __method__, self.class],
78
+ [7, 'send', __method__, self.class],
79
+ [4, 'call', :add, self.class],
80
+ [5, 'line', :add, self.class],
81
+ [5, 'send', :add, self.class],
82
+ [5, 'c-call', :+, Fixnum],
83
+ [5, 'c-return', :+, Fixnum],
84
+ [6, 'return', :add, self.class],
85
+ [6, 'leave', :add, self.class],
86
+ [8, 'line', __method__, self.class],
87
+ [8, 'send', __method__, self.class],
88
+ [8, 'c-call', :set_trace_func, Kernel]
89
+ ]
79
90
  checkit(@events, expected)
80
91
  end
81
92
 
@@ -96,17 +107,23 @@ class TestSetTraceFunc < Test::Unit::TestCase
96
107
  [4, 'c-return', :inherited, Class],
97
108
  [4, 'class', nil, nil],
98
109
  [5, 'line', nil, nil],
110
+ [5, 'send', nil, nil],
99
111
  [5, 'c-call', :method_added, Module],
100
112
  [5, 'c-return', :method_added, Module],
101
113
  [7, 'end', nil, nil],
114
+ [7, 'leave', nil, nil],
102
115
  [8, 'line', __method__, self.class],
116
+ [8, 'send', __method__, self.class],
103
117
  [8, 'c-call', :new, Class],
104
118
  [8, 'c-call', :initialize, BasicObject],
105
119
  [8, 'c-return', :initialize, BasicObject],
106
120
  [8, 'c-return', :new, Class],
121
+ [8, 'send', __method__, Class],
107
122
  [5, 'call', :bar, Foo],
108
123
  [6, 'return', :bar, Foo],
124
+ [6, 'leave', :bar, Foo],
109
125
  [9, 'line', __method__, self.class],
126
+ [9, 'send', __method__, self.class],
110
127
  [9, 'c-call', :clear_trace_func, Kernel]]
111
128
  checkit(@events, expected)
112
129
  end
@@ -124,19 +141,27 @@ class TestSetTraceFunc < Test::Unit::TestCase
124
141
  9: foo(false)
125
142
  10: set_trace_func(nil)
126
143
  EOF
127
- expected = [[ 4, 'line', __method__, self.class],
128
- [ 4, 'c-call', :method_added, Module],
129
- [ 4, 'c-return', :method_added, Module],
130
- [ 8, 'line', __method__, self.class],
131
- [ 4, 'call', :foo, self.class],
132
- [ 5, 'line', :foo, self.class],
133
- [ 5, 'return', :foo, self.class],
134
- [ 9, 'line', :test_return, self.class],
135
- [ 4, 'call', :foo, self.class],
136
- [ 5, 'line', :foo, self.class],
137
- [ 7, 'return', :foo, self.class],
138
- [10, 'line', :test_return, self.class],
139
- [10, 'c-call', :set_trace_func, Kernel]]
144
+ expected =
145
+ [
146
+ [ 4, 'line', __method__, self.class],
147
+ [ 4, 'send', __method__, self.class],
148
+ [ 4, 'c-call', :method_added, Module],
149
+ [ 4, 'c-return', :method_added, Module],
150
+ [ 8, 'line', __method__, self.class],
151
+ [ 8, 'send', __method__, self.class],
152
+ [ 4, 'call', :foo, self.class],
153
+ [ 5, 'line', :foo, self.class],
154
+ [ 5, 'return', :foo, self.class],
155
+ [ 5, 'leave', :foo, self.class],
156
+ [ 9, 'line', :test_return, self.class],
157
+ [ 9, 'send', :test_return, self.class],
158
+ [ 4, 'call', :foo, self.class],
159
+ [ 5, 'line', :foo, self.class],
160
+ [ 7, 'return', :foo, self.class],
161
+ [10, 'line', :test_return, self.class],
162
+ [10, 'leave', :test_return, self.class],
163
+ [10, 'send', :test_return, self.class],
164
+ [10, 'c-call', :set_trace_func, Kernel]]
140
165
  checkit(@events, expected)
141
166
  end
142
167
 
@@ -153,16 +178,22 @@ class TestSetTraceFunc < Test::Unit::TestCase
153
178
  9: set_trace_func(nil)
154
179
  EOF
155
180
 
156
- expected = [[4, 'line', __method__, self.class],
157
- [4, 'c-call', :method_added, Module],
158
- [4, 'c-return', :method_added, Module],
159
- [8, 'line', __method__, self.class],
160
- [4, 'call', :foo, self.class],
161
- [5, 'line', :foo, self.class],
162
- [6, 'line', :foo, self.class],
163
- [7, 'return', :foo, self.class],
164
- [9, 'line', :test_return2, self.class],
165
- [9, 'c-call', :set_trace_func, Kernel]]
181
+ expected =
182
+ [
183
+ [4, 'line', __method__, self.class],
184
+ [4, 'send', __method__, self.class],
185
+ [4, 'c-call', :method_added, Module],
186
+ [4, 'c-return', :method_added, Module],
187
+ [8, 'line', __method__, self.class],
188
+ [8, 'send', __method__, self.class],
189
+ [4, 'call', :foo, self.class],
190
+ [5, 'line', :foo, self.class],
191
+ [6, 'line', :foo, self.class],
192
+ [7, 'return', :foo, self.class],
193
+ [7, 'leave', :foo, self.class],
194
+ [9, 'line', :test_return2, self.class],
195
+ [9, 'send', :test_return2, self.class],
196
+ [9, 'c-call', :set_trace_func, Kernel]]
166
197
  @events.each_with_index{|e, i|
167
198
  assert_equal(e, @events[i], showit(@events, expected))}
168
199
  assert_equal(expected.size, @events.size, showit(@events, expected))
@@ -181,23 +212,30 @@ class TestSetTraceFunc < Test::Unit::TestCase
181
212
  8: set_trace_func(nil)
182
213
  EOF
183
214
 
184
- expected = [[4, 'line', __method__, self.class],
185
- [5, 'line', __method__, self.class],
186
- [5, 'c-call', :raise, Kernel],
187
- [5, 'c-call', :exception, Exception],
188
- [5, 'c-call', :initialize, Exception],
189
- [5, 'c-return', :initialize, Exception],
190
- [5, 'c-return', :exception, Exception],
191
- [5, 'c-call', :backtrace, Exception],
192
- [5, 'c-return', :backtrace, Exception],
193
- [5, 'c-call', :set_backtrace, Exception],
194
- [5, 'c-return', :set_backtrace, Exception],
195
- [5, 'raise', :test_raise, $e],
196
- [5, 'c-return', :raise, Kernel],
197
- [6, 'c-call', :===, Module],
198
- [6, 'c-return', :===, Module],
199
- [8, 'line', __method__, self.class],
200
- [8, 'c-call', :set_trace_func, Kernel]]
215
+ expected =
216
+ [
217
+ [4, 'line', __method__, self.class],
218
+ [5, 'line', __method__, self.class],
219
+ [5, 'send', __method__, Kernel],
220
+ [5, 'c-call', :raise, Kernel],
221
+ [5, 'c-call', :exception, Exception],
222
+ [5, 'c-call', :initialize, Exception],
223
+ [5, 'c-return', :initialize, Exception],
224
+ [5, 'c-return', :exception, Exception],
225
+ [5, 'c-call', :backtrace, Exception],
226
+ [5, 'c-return', :backtrace, Exception],
227
+ [5, 'c-call', :set_backtrace, Exception],
228
+ [5, 'c-return', :set_backtrace, Exception],
229
+ [5, 'raise', :test_raise, $e],
230
+ [5, 'c-return', :raise, Kernel],
231
+ [5, 'send', __method__, Kernel],
232
+ [6, 'c-call', :===, Module],
233
+ [6, 'c-return', :===, Module],
234
+ [7, 'leave', __method__, Module],
235
+ [8, 'line', __method__, self.class],
236
+ [8, 'send', __method__, self.class],
237
+ [8, 'c-call', :set_trace_func, Kernel]
238
+ ]
201
239
  checkit(events, expected)
202
240
  end
203
241
 
@@ -211,13 +249,17 @@ class TestSetTraceFunc < Test::Unit::TestCase
211
249
  8: set_trace_func(nil)
212
250
  EOF
213
251
 
214
- expected = [[4, 'line', __method__, self.class],
252
+ expected = [
253
+ [4, 'line', __method__, self.class],
254
+ [4, 'send', __method__, self.class],
215
255
  [4, 'c-call', :any?, Enumerable],
216
256
  [4, 'c-call', :each, Array],
217
257
  [4, 'line', __method__, self.class],
258
+ [4, 'leave', __method__, self.class],
218
259
  [4, 'c-return', :each, Array],
219
260
  [4, 'c-return', :any?, Enumerable],
220
261
  [5, 'line', __method__, self.class],
262
+ [5, 'send', __method__, self.class],
221
263
  [5, 'c-call', :set_trace_func, Kernel]]
222
264
  checkit(events, expected)
223
265
  end
@@ -258,7 +300,9 @@ class TestSetTraceFunc < Test::Unit::TestCase
258
300
 
259
301
  expected = [[1, 'c-return', :set_trace_func, Thread, :set],
260
302
  [2, 'line', __method__, self.class, :set],
261
- [2, 'c-call', :add_trace_func, Thread, :set]]
303
+ [2, 'send', :test_thread_trace, TestSetTraceFunc, :set],
304
+ [2, 'c-call', :add_trace_func, Thread, :set],
305
+ ]
262
306
  expected.each do |e|
263
307
  assert_equal(e, events[:set].shift, showit(events, expected))
264
308
  end
@@ -269,21 +313,29 @@ class TestSetTraceFunc < Test::Unit::TestCase
269
313
  [3, 'c-return', :inherited, Class],
270
314
  [3, 'class', nil, nil],
271
315
  [4, 'line', nil, nil],
316
+ [4, 'send', nil, nil],
272
317
  [4, 'c-call', :method_added, Module],
273
318
  [4, 'c-return', :method_added, Module],
274
319
  [7, 'end', nil, nil],
320
+ [7, 'leave', nil, nil],
275
321
  [8, 'line', __method__, self.class],
322
+ [8, 'send', __method__, self.class],
276
323
  [8, 'c-call', :new, Class],
277
324
  [8, 'c-call', :initialize, BasicObject],
278
325
  [8, 'c-return', :initialize, BasicObject],
279
326
  [8, 'c-return', :new, Class],
327
+ [8, 'send', :test_thread_trace, TestSetTraceFunc],
280
328
  [4, 'call', :foo, ThreadTraceInnerClass],
281
329
  [5, 'line', :foo, ThreadTraceInnerClass],
330
+ [5, 'send', :foo, ThreadTraceInnerClass],
282
331
  [5, 'c-call', :+, Fixnum],
283
332
  [5, 'c-return', :+, Fixnum],
284
333
  [6, 'return', :foo, ThreadTraceInnerClass],
334
+ [6, 'leave', :foo, ThreadTraceInnerClass],
285
335
  [9, 'line', __method__, self.class],
286
- [9, 'c-call', :set_trace_func, Thread]].each do |e|
336
+ [9, 'send', __method__, self.class],
337
+ [9, 'c-call', :set_trace_func, Thread]
338
+ ].each do |e|
287
339
  [:set, :add].each do |type|
288
340
  assert_equal(e + [type], events[type].shift)
289
341
  end
@@ -4,12 +4,14 @@ require_relative '../../ext/thread_frame'
4
4
 
5
5
  class TestTracingMasks < Test::Unit::TestCase
6
6
  @@EVENT2MASK = {
7
- 'line' => 0x01,
8
- 'call' => 0x08,
9
- 'return' => 0x10,
10
- 'c-call' => 0x20,
11
- 'c-return' => 0x40,
12
- 'raise' => 0x80,
7
+ 'line' => 0x0001,
8
+ 'call' => 0x0008,
9
+ 'return' => 0x0010,
10
+ 'c-call' => 0x0020,
11
+ 'c-return' => 0x0040,
12
+ 'raise' => 0x0080,
13
+ 'send' => 0x0400,
14
+ 'leave' => 0x0800,
13
15
  }
14
16
 
15
17
  def something_to_test(n)
metadata CHANGED
@@ -4,8 +4,8 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 37
8
- version: "0.37"
7
+ - 38
8
+ version: "0.38"
9
9
  platform: ruby
10
10
  authors:
11
11
  - R. Bernstein
@@ -13,7 +13,7 @@ autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
15
 
16
- date: 2011-02-01 00:00:00 -05:00
16
+ date: 2011-03-15 00:00:00 -04:00
17
17
  default_executable:
18
18
  dependencies: []
19
19
 
@@ -33,46 +33,42 @@ files:
33
33
  - Makefile
34
34
  - LICENSE
35
35
  - NEWS
36
+ - include/thread_pthread.h
36
37
  - include/node.h
37
- - include/ruby19_externs.h
38
38
  - include/method_mini.h
39
- - include/thread_pthread.h
39
+ - include/ruby19_externs.h
40
40
  - include/vm_core_mini.h
41
- - lib/thread_frame.rb
42
41
  - lib/iseq_extra.rb
42
+ - lib/thread_frame.rb
43
43
  - ext/iseq_extra.c
44
44
  - ext/thread_frame.c
45
- - ext/thread_extra.c
46
45
  - ext/proc_extra.c
46
+ - ext/thread_extra.c
47
+ - ext/thread_frame.h
48
+ - ext/proc_extra.h
49
+ - ext/thread_pthread.h
50
+ - ext/node.h
47
51
  - ext/thread_extra.h
48
- - ext/iseq_mini.h
49
52
  - ext/iseq_extra.h
50
- - ext/node.h
51
- - ext/thread_pthread.h
52
- - ext/proc_extra.h
53
- - test/ruby/test_tracefunc_adds.rb
54
- - test/ruby/test_brkpt.rb
55
- - test/ruby/test_disasm.rb
56
- - test/ruby/test_iseq.rb
57
- - test/ruby/test_tracefunc_raise.rb
58
- - test/unit/test-sp-size.rb
59
- - test/unit/test-iseq-brkpt.rb
53
+ - ext/iseq_mini.h
54
+ - test/unit/test-trace.rb
60
55
  - test/unit/test-iseq-save.rb
61
- - test/unit/test-binding.rb
62
56
  - test/unit/test-prev.rb
57
+ - test/unit/test-source.rb
63
58
  - test/unit/test-lib-iseq.rb
64
59
  - test/unit/test-return-stop.rb
65
- - test/unit/test-iseq.rb
66
- - test/unit/cfunc-use.rb
67
- - test/unit/test-argc.rb
60
+ - test/unit/test-proc.rb
68
61
  - test/unit/test-invalid.rb
62
+ - test/unit/test-argc.rb
63
+ - test/unit/cfunc-use.rb
64
+ - test/unit/test-binding.rb
69
65
  - test/unit/test-lib-iseq-extra.rb
70
- - test/unit/test-thread-trace-masks.rb
71
- - test/unit/test-proc.rb
72
66
  - test/unit/test-thread.rb
67
+ - test/unit/test-iseq-brkpt.rb
68
+ - test/unit/test-iseq.rb
69
+ - test/unit/test-thread-trace-masks.rb
73
70
  - test/unit/test-settracefunc.rb
74
- - test/unit/test-trace.rb
75
- - test/unit/test-source.rb
71
+ - test/unit/test-sp-size.rb
76
72
  - threadframe.rd
77
73
  - ext/extconf.rb
78
74
  has_rdoc: true
@@ -84,7 +80,7 @@ rdoc_options:
84
80
  - --main
85
81
  - README.md
86
82
  - --title
87
- - ThreadFrame 0.37 Documentation
83
+ - ThreadFrame 0.38 Documentation
88
84
  require_paths:
89
85
  - lib
90
86
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -1,60 +0,0 @@
1
- require 'test/unit'
2
-
3
- class TestISeqBrkpt < Test::Unit::TestCase
4
-
5
- def setup
6
- @original_compile_option = RubyVM::InstructionSequence.compile_option
7
- RubyVM::InstructionSequence.compile_option = {
8
- :trace_instruction => false,
9
- :specialized_instruction => false
10
- }
11
- end
12
-
13
- def teardown
14
- set_trace_func(nil)
15
- RubyVM::InstructionSequence.compile_option = @original_compile_option
16
- end
17
-
18
- def test_iseq_brkpt
19
- iseq = RubyVM::InstructionSequence.compile('x=1; y=2')
20
- assert iseq
21
- assert_equal(nil, iseq.brkpts)
22
- assert_equal(true, iseq.brkpt_alloc)
23
- assert_equal([], iseq.brkpts)
24
- assert_equal(false, iseq.brkpt_alloc)
25
-
26
- assert_equal(true, iseq.brkpt_set(0))
27
- assert_equal(1, iseq.brkpts.size)
28
- assert_equal(true, iseq.brkpt_get(0), 'Offset 0 should be set')
29
- assert_equal(true, iseq.brkpt_unset(0),'Offset 0 should be unset')
30
- assert_equal(false, iseq.brkpt_get(0), 'Offset 0 should be unset now')
31
- assert_equal(true, iseq.brkpt_unset(0),
32
- 'Offset 0 should be unset again')
33
- assert_raises TypeError do iseq.brkpt_get(100) end
34
- assert_equal(true, iseq.brkpt_dealloc)
35
- assert_equal(false, iseq.brkpt_dealloc)
36
- assert_equal(true, iseq.brkpt_unset(0),
37
- 'Offset 0 should be unset even when deallocated')
38
-
39
- assert_raises TypeError do iseq.brkpt_set('a') end
40
-
41
- iseq.brkpt_set(2)
42
- iseq.brkpt_set(4)
43
- events = []
44
- eval <<-EOF.gsub(/^.*?: /, "")
45
- 1: set_trace_func(Proc.new { |event, file, lineno, mid, binding, klass|
46
- 2: events << [event, lineno, mid, klass]
47
- 3: })
48
- 4: iseq.eval
49
- 5: set_trace_func(nil)
50
- EOF
51
- # puts iseq.disassemble
52
- brkpt_events = events.select{|item| item[0] == 'brkpt'}
53
- assert_equal(2, brkpt_events.size,
54
- "Expecting to see 2 brkpts in #{events}.inspect")
55
- assert_equal(true, iseq.brkpt_dealloc)
56
- end
57
- end
58
-
59
- # We want to double-check we didn't mess up any pointers somewhere.
60
- at_exit { GC.start }
@@ -1,17 +0,0 @@
1
- # Some simple tests of RubyVM::InstructionSequence#disasm, and
2
- # #disasm_nochildren
3
- require 'test/unit'
4
-
5
- class TestDisasmClass < Test::Unit::TestCase
6
-
7
- def test_basic
8
- assert_equal(RubyVM::InstructionSequence.compile('1+2').disassemble,
9
- RubyVM::InstructionSequence.compile('1+2').disasm)
10
-
11
- p='def five; 5 end; five'
12
- s1=RubyVM::InstructionSequence.compile(p).disasm
13
- assert_equal String, s1.class, 'disasm output should be a string'
14
- s2=RubyVM::InstructionSequence.compile(p).disasm_nochildren
15
- assert_equal true, s1.size > s2.size
16
- end
17
- end
@@ -1,50 +0,0 @@
1
- # See that setting ISEQS__ and SCRIPT_ISEQS__ saves
2
- # RubyVM::Instruction_sequenses
3
- require 'test/unit'
4
-
5
- class TestIseqAccess < Test::Unit::TestCase
6
- def setup
7
- old_verbosity = $VERBOSE
8
- $VERBOSE = nil
9
- Kernel.const_set(:ISEQS__, {})
10
- Kernel.const_set(:SCRIPT_ISEQS__, {})
11
- $VERBOSE = old_verbosity
12
- end
13
-
14
- def teardown
15
- old_verbosity = $VERBOSE
16
- $VERBOSE = nil
17
- Kernel.const_set(:ISEQS__, nil)
18
- Kernel.const_set(:SCRIPT_ISEQS__, nil)
19
- $VERBOSE = old_verbosity
20
- end
21
-
22
- def test_basic
23
- sizes=[]
24
- [ISEQS__, SCRIPT_ISEQS__].each do |iseq_hash|
25
- sizes << iseq_hash.size
26
- end
27
- # defining five should trigger five instruction sequence additions
28
- # to ISEQS__ and SCRIPT_ISEQS__
29
- #
30
- eval 'def five; 5 end'
31
- assert_equal sizes[0], sizes[1]
32
- [SCRIPT_ISEQS__, ISEQS__].each do |iseq_hash|
33
- assert_equal true, iseq_hash.size > sizes.pop
34
- assert_equal Hash, iseq_hash.class
35
- a = iseq_hash.first
36
- assert_equal Array, a.class
37
- assert_equal RubyVM::InstructionSequence, iseq_hash.values[0][0].class
38
- end
39
- end
40
-
41
- # Check RubyVM::InstructionSequence#arity
42
- def test_arity
43
- eval 'def five; 5 end'
44
- eval 'def add(a,b); a+b end'
45
- eval 'def splat(*a); 5 end'
46
- [['five', 0,], ['add', 2], ['splat', -1]].each do |meth, expect|
47
- assert_equal(expect, ISEQS__[meth][0].arity)
48
- end
49
- end
50
- end
@@ -1,145 +0,0 @@
1
- require 'test/unit'
2
-
3
- # tests set_trace_func with event bitmasks, clear_trace_func,
4
- # Newer changes
5
- class TestSetTraceFuncAdds < Test::Unit::TestCase
6
-
7
- # Some of the below setup is similar to what is in lib/trace_mod.rb of
8
- # rb-trace
9
- @@NO_EVENT_MASK = 0x0000
10
- @@LINE_EVENT_MASK = 0x0001
11
- @@CLASS_EVENT_MASK = 0x0002
12
- @@END_EVENT_MASK = 0x0004
13
- @@CALL_EVENT_MASK = 0x0008
14
- @@RETURN_EVENT_MASK = 0x0010
15
- @@C_CALL_EVENT_MASK = 0x0020
16
- @@C_RETURN_EVENT_MASK = 0x0040
17
- @@RAISE_EVENT_MASK = 0x0080
18
- @@INSN_EVENT_MASK = 0x0100
19
- @@ALL_EVENTS_MASK = (0xffff & ~@@INSN_EVENT_MASK)
20
-
21
- @@EVENT2MASK = {
22
- 'line' => @@LINE_EVENT_MASK,
23
- 'call' => @@CALL_EVENT_MASK,
24
- 'return' => @@RETURN_EVENT_MASK,
25
- 'c-call' => @@C_CALL_EVENT_MASK,
26
- 'c-return' => @@C_RETURN_EVENT_MASK,
27
- 'c-raise' => @@RAISE_EVENT_MASK
28
- }
29
-
30
- # Convert +events+ into a Fixnum bitmask used internally by Ruby.
31
- # Parameter +events+ should be Enumerable and each element should
32
- # either be a Fixnum mask value or something that can be converted
33
- # to a symbol. If the latter, the case is not important as we'll
34
- # downcase the string representation.
35
- def events2bitmask(event_list)
36
- bitmask = @@NO_EVENT_MASK
37
- event_list.each do |event|
38
- bitmask |= @@EVENT2MASK[event]
39
- end
40
- return bitmask
41
- end
42
-
43
- def setup
44
- @original_compile_option = RubyVM::InstructionSequence.compile_option
45
- RubyVM::InstructionSequence.compile_option = {
46
- :trace_instruction => true,
47
- :specialized_instruction => false
48
- }
49
- @proc_template = 'Proc.new { |event, file, lineno, mid, binding, klass|
50
- %s << [event, lineno, mid, klass]}'
51
- end
52
-
53
- def teardown
54
- clear_trace_func
55
- RubyVM::InstructionSequence.compile_option = @original_compile_option
56
- end
57
-
58
- def test_eventmask
59
- returned_tuples =
60
- [['line', 5, :test_eventmask, self.class],
61
- ['class', 5, nil, nil],
62
- ['end', 5, nil, nil],
63
- ['line', 6, :test_eventmask, self.class],
64
- ['call', 1, :five, self.class],
65
- ['line', 1, :five, self.class],
66
- ['return', 1, :five, self.class],
67
- ['c-call', 6, :any?, Enumerable],
68
- ['c-call', 6, :each, Array],
69
- ['line', 6, :test_eventmask, self.class],
70
- ['c-return', 6, :each, Array],
71
- ['c-return', 6, :any?, Enumerable],
72
- ['line', 7, :test_eventmask, self.class],
73
- ['c-call', 7, :clear_trace_func, Kernel]]
74
-
75
- [[], nil,
76
- %w(line),
77
- %w(call line),
78
- %w(c-call c-return line),
79
- ].each do |event_list|
80
- tuples = []
81
- event_mask = if event_list
82
- events2bitmask(event_list)
83
- else
84
- @@ALL_EVENTS_MASK
85
- end
86
- cmd = <<-EOF.gsub(/^.*?: /, '')
87
- 1: def five; 5 end
88
- 2: p1 = #{@proc_template}
89
- 3: set_trace_func(p1, #{event_mask})
90
- 4: class Foo; end
91
- 5: [1,2,five].any? {|n| n}
92
- 6: clear_trace_func
93
- EOF
94
- eval(cmd % 'tuples')
95
- expected = if event_list
96
- returned_tuples.select{|x| !([x[0]] & event_list).empty?}
97
- else
98
- returned_tuples
99
- end
100
- assert_equal(expected, tuples,
101
- "Error filtering #{event_list}")
102
- # p tuples
103
- end
104
- end
105
-
106
- def test_chained_hook
107
- tuples1 = []
108
- tuples2 = []
109
- cmd = <<-EOF.gsub(/^.*?: /, '')
110
- 1: def five; 5 end
111
- 2: p1 = #{@proc_template}
112
- 3: p2 = #{@proc_template}
113
- 4: add_trace_func(p1, @@LINE_EVENT_MASK)
114
- 5: add_trace_func(p2, @@CALL_EVENT_MASK)
115
- 6: class Foo; end
116
- 7: [1,2,five].any? {|n| n}
117
- EOF
118
- eval(cmd % %w(tuples1 tuples2))
119
- clear_trace_func
120
- assert_equal([
121
- ["line", 7, :test_chained_hook, self.class],
122
- ["line", 8, :test_chained_hook, self.class],
123
- ["line", 9, :test_chained_hook, self.class],
124
- ["line", 1, :five, self.class],
125
- ["line", 9, :test_chained_hook, self.class],
126
- ], tuples1[0..-2],
127
- 'line filtering')
128
- assert_equal([["call", 1, :five, self.class]], tuples2,
129
- 'call filtering')
130
- end
131
-
132
- def test_trace_insn
133
- tuples = []
134
- cmd = <<-EOF.gsub(/^.*?: /, '')
135
- 1: p = #{@proc_template}
136
- 2: add_trace_func(p, @@INSN_EVENT_MASK)
137
- 4: x = 1
138
- 3: y = 2
139
- EOF
140
- eval cmd % 'tuples'
141
- clear_trace_func
142
- assert_equal true, !tuples.empty?, 'triggered instruction events'
143
- assert_equal true, tuples.all?{|t| 'vm-insn' == t[0]}, 'instruction events'
144
- end
145
- end
@@ -1,26 +0,0 @@
1
- require 'test/unit'
2
-
3
- # tests that we a trace hook has access to the runtime exception Object
4
- # when it is called through a raise event
5
-
6
- class TestTracefuncRaise < Test::Unit::TestCase
7
-
8
- def test_basic
9
- tuples = []
10
- p = Proc.new {
11
- |event, file, lineno, mid, binding, klass|
12
- tuples << klass
13
- }
14
- msg = 'this is a message'
15
- set_trace_func(p, 0x0080)
16
- begin ; x = 1/0; rescue; end
17
- begin ; raise RuntimeError, msg; rescue; end
18
- clear_trace_func
19
- assert_equal(2, tuples.size,
20
- "Wrong number of tuples captured #{tuples.inspect}")
21
- assert_equal msg, tuples[1].message
22
- assert_equal([ZeroDivisionError, RuntimeError], tuples.map{|t| t.class},
23
- "Mismatched tuples classes in #{tuples.inspect}")
24
-
25
- end
26
- end