rb-threadframe 0.37 → 0.38

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/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