rb-threadframe 0.39 → 0.40
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 +6 -0
- data/README.md +6 -3
- data/Rakefile +4 -4
- data/ext/1.9.3/thread_frame.c +22 -0
- data/ext/extconf.rb +2 -2
- data/ext/version.h +1 -0
- data/lib/iseq_extra.rb +7 -6
- data/lib/thread_frame.rb +9 -1
- data/test/unit/cfunc-use.rb +1 -1
- data/test/unit/test-argc.rb +3 -2
- data/test/unit/test-binding.rb +5 -5
- data/test/unit/{test-thread.rb → test-frame.rb} +36 -33
- data/test/unit/test-invalid.rb +6 -5
- data/test/unit/test-iseq-brkpt.rb +4 -4
- data/test/unit/test-iseq-save.rb +1 -1
- data/test/unit/test-iseq.rb +10 -9
- data/test/unit/test-lib-iseq-extra.rb +14 -5
- data/test/unit/test-lib-iseq.rb +9 -8
- data/test/unit/test-prev.rb +12 -12
- data/test/unit/test-proc.rb +4 -1
- data/test/unit/test-return-stop.rb +3 -4
- data/test/unit/test-settracefunc.rb +67 -43
- data/test/unit/test-source.rb +7 -8
- data/test/unit/test-sp-size.rb +4 -5
- data/test/unit/test-thread-trace-masks.rb +2 -1
- data/test/unit/test-trace.rb +4 -4
- data/threadframe.rd +31 -31
- metadata +31 -57
- data/ext/iseq_extra.c +0 -441
- data/ext/iseq_extra.h +0 -8
- data/ext/iseq_mini.h +0 -41
- data/ext/node.h +0 -483
- data/ext/proc_extra.c +0 -186
- data/ext/proc_extra.h +0 -3
- data/ext/thread_extra.c +0 -84
- data/ext/thread_extra.h +0 -5
- data/ext/thread_frame.c +0 -1165
- data/ext/thread_frame.h +0 -4
- data/ext/thread_pthread.h +0 -24
- data/test/ruby/test_brkpt.rb +0 -60
- data/test/ruby/test_disasm.rb +0 -17
- data/test/ruby/test_iseq.rb +0 -50
- data/test/ruby/test_tracefunc_raise.rb +0 -26
data/test/unit/test-sp-size.rb
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
require 'test/unit'
|
2
2
|
|
3
|
-
|
4
|
-
require_relative '../../ext/thread_frame'
|
3
|
+
require_relative '../../ext/thread_frame' if '1.9.2' == RUBY_VERSION
|
5
4
|
|
6
|
-
# Test
|
5
|
+
# Test accessing and settign RubyVM::Frame stack data
|
7
6
|
class TestSpSize < Test::Unit::TestCase
|
8
7
|
|
9
8
|
def sizes
|
10
|
-
tf = RubyVM::
|
9
|
+
tf = RubyVM::Frame::current
|
11
10
|
ary = []
|
12
11
|
0.upto(2) do |i|
|
13
12
|
ary << tf.sp_size
|
@@ -37,7 +36,7 @@ class TestSpSize < Test::Unit::TestCase
|
|
37
36
|
assert_equal(f1_s[1..-1], f2_s[1..-1])
|
38
37
|
|
39
38
|
assert_raises ArgumentError do
|
40
|
-
tf = RubyVM::
|
39
|
+
tf = RubyVM::Frame.current
|
41
40
|
tf.sp_set(tf.sp_size, "Should not be able to set this.")
|
42
41
|
end
|
43
42
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# Test of additional tracing flag use to selectively turn on off tracing
|
2
2
|
require 'test/unit'
|
3
|
-
|
3
|
+
|
4
|
+
require_relative '../../ext/thread_frame' if '1.9.2' == RUBY_VERSION
|
4
5
|
|
5
6
|
class TestTracingMasks < Test::Unit::TestCase
|
6
7
|
@@EVENT2MASK = {
|
data/test/unit/test-trace.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# Test of additional tracing flag use to selectively turn on off tracing
|
2
2
|
require 'test/unit'
|
3
|
-
require_relative '../../ext/thread_frame'
|
3
|
+
require_relative '../../ext/thread_frame' if '1.9.2' == RUBY_VERSION
|
4
4
|
|
5
5
|
class TestTracing < Test::Unit::TestCase
|
6
6
|
def test_basic_query_set_unset
|
7
|
-
tf = RubyVM::
|
7
|
+
tf = RubyVM::Frame::current
|
8
8
|
# Test default values
|
9
9
|
assert_equal(false, tf.trace_off?)
|
10
10
|
assert_equal(false, tf.return_stop?)
|
@@ -25,14 +25,14 @@ class TestTracing < Test::Unit::TestCase
|
|
25
25
|
def test_trace_off
|
26
26
|
@levels = []
|
27
27
|
def trace_hook(event, file, line, id, binding, klass)
|
28
|
-
@levels << RubyVM::
|
28
|
+
@levels << RubyVM::Frame::current.stack_size
|
29
29
|
end
|
30
30
|
|
31
31
|
def baz
|
32
32
|
6
|
33
33
|
end
|
34
34
|
def bar(set_off)
|
35
|
-
RubyVM::
|
35
|
+
RubyVM::Frame::current.trace_off = true if set_off
|
36
36
|
baz
|
37
37
|
5
|
38
38
|
end
|
data/threadframe.rd
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
# = NAME
|
2
|
-
# +RubyVM+::+
|
2
|
+
# +RubyVM+::+Frame+
|
3
3
|
#
|
4
4
|
# = SYNOPSES
|
5
5
|
#
|
6
|
-
# The +RubyVM+::+
|
6
|
+
# The +RubyVM+::+Frame+ class gives call-stack frame information
|
7
7
|
# (controlled access to +rb_control_frame_t+)
|
8
8
|
#
|
9
9
|
#
|
10
10
|
# It is possible that a The +Thread+::+Frame+ may be proposed for
|
11
|
-
# all Ruby 1.9 implementations. +RubyVM+::+
|
11
|
+
# all Ruby 1.9 implementations. +RubyVM+::+Frame+
|
12
12
|
# contains routines in the YARV 1.9 implementation.
|
13
13
|
#
|
14
|
-
# Should there be a +Thread+::+Frame+ +RubyVM+::+
|
14
|
+
# Should there be a +Thread+::+Frame+ +RubyVM+::+Frame+ would be
|
15
15
|
# a subclass of +Thread+::+Frame+. In code:
|
16
16
|
#
|
17
17
|
# class Thread
|
@@ -19,11 +19,11 @@
|
|
19
19
|
# # ...
|
20
20
|
# end
|
21
21
|
# def threadframe
|
22
|
-
# RubyVM::
|
22
|
+
# RubyVM::Frame.new(self) # or possibly Thread::Frame.new(self)
|
23
23
|
# end
|
24
24
|
# end
|
25
25
|
#
|
26
|
-
# class RubyVM::
|
26
|
+
# class RubyVM::Frame < Thread::Frame # In YARV
|
27
27
|
# def initialize(thread_object)
|
28
28
|
# # implementation-specific code
|
29
29
|
# end
|
@@ -36,25 +36,25 @@
|
|
36
36
|
# A +RubyVM+::Thread+Frame+ contains information from a frame running +Thread+
|
37
37
|
# object, and the information may change or disappear in the course of
|
38
38
|
# running that thread. Therefore, it is advisable ensure that the
|
39
|
-
# threads of the
|
39
|
+
# threads of the Frame objects are blocked.
|
40
40
|
#
|
41
41
|
#
|
42
|
-
# === RubyVM::
|
42
|
+
# === RubyVM::Frame::new(thread_object)
|
43
43
|
# Creates a thread-frame object for the given thread object.
|
44
44
|
#
|
45
|
-
# === RubyVM::
|
46
|
-
# Shorthand for RubyVM::
|
45
|
+
# === RubyVM::Frame::current
|
46
|
+
# Shorthand for RubyVM::Frame.new(Thread::current)
|
47
47
|
#
|
48
48
|
# === Thread#threadframe
|
49
49
|
# tf = Thread::current.threadframe()
|
50
50
|
#
|
51
51
|
# Creates a thread-frame object for the given thread object.
|
52
52
|
# Note:
|
53
|
-
# Thread::current.threadframe() == RubyVM::
|
53
|
+
# Thread::current.threadframe() == RubyVM::Frame.new(Thread::current)
|
54
54
|
#
|
55
|
-
# == RubyVM::
|
55
|
+
# == RubyVM::Frame Instance Methods
|
56
56
|
#
|
57
|
-
# === RubyVM::
|
57
|
+
# === RubyVM::Frame#prev
|
58
58
|
# tf.prev(n) -> tf or nil
|
59
59
|
# tf.prev() -> tf or nil # same as tf.prev(1)
|
60
60
|
#
|
@@ -65,7 +65,7 @@
|
|
65
65
|
# tf. A negative number of a number greater than the number of frames
|
66
66
|
# returns nil.
|
67
67
|
#
|
68
|
-
# === RubyVM::
|
68
|
+
# === RubyVM::Frame#invalid?
|
69
69
|
# tf.invalid?() -> boolean
|
70
70
|
#
|
71
71
|
# Returns true if the frame is no longer valid. On the other hand,
|
@@ -78,24 +78,24 @@
|
|
78
78
|
# variable is active.
|
79
79
|
#
|
80
80
|
#
|
81
|
-
# === RubyVM::
|
81
|
+
# === RubyVM::Frame#thread
|
82
82
|
# tf.thread() -> Thread
|
83
|
-
# RubyVM::
|
83
|
+
# RubyVM::Frame.current().thread == Thread.current
|
84
84
|
#
|
85
|
-
# === RubyVM::
|
85
|
+
# === RubyVM::Frame#type
|
86
86
|
# tf.type() -> 'C' or 'Ruby'
|
87
87
|
#
|
88
88
|
# Indicates whether the frame is implemented in C or Ruby.
|
89
89
|
#
|
90
|
-
# === RubyVM::
|
90
|
+
# === RubyVM::Frame#source_container
|
91
91
|
# RubyVM::Threadframe#source_container() -> [Type, String]
|
92
92
|
#
|
93
93
|
# Returns a tuple representing kind of container, e.g. file
|
94
94
|
# eval'd string object, and the name of the container. If file,
|
95
95
|
# it would be a file name. If an eval'd string it might be the string.
|
96
96
|
#
|
97
|
-
# === RubyVM::
|
98
|
-
# RubyVM::
|
97
|
+
# === RubyVM::Frame#source_location
|
98
|
+
# RubyVM::Frame#.source_location() -> Array
|
99
99
|
#
|
100
100
|
# Returns an array of source location positions that match
|
101
101
|
# +tf.instruction_offset+. A source location position is left
|
@@ -103,12 +103,12 @@
|
|
103
103
|
# and start and end column, or a start line number, start column, end
|
104
104
|
# line number, end column.
|
105
105
|
#
|
106
|
-
# === RubyVM::
|
107
|
-
# RubyVM::
|
106
|
+
# === RubyVM::Frame#stack_size
|
107
|
+
# RubyVM::Frame#.stack_size -> Fixnum
|
108
108
|
#
|
109
109
|
# Returns the number of entries
|
110
110
|
#
|
111
|
-
# === RubyVM::
|
111
|
+
# === RubyVM::Frame#binding
|
112
112
|
# tf.binding() -> binding
|
113
113
|
#
|
114
114
|
#
|
@@ -117,28 +117,28 @@
|
|
117
117
|
# execution of the program, variables may spring into existence and
|
118
118
|
# values may change.
|
119
119
|
|
120
|
-
# == RubyVM::
|
120
|
+
# == RubyVM::Frame
|
121
121
|
#
|
122
122
|
# === RubyVM::new(thread_object)
|
123
123
|
|
124
|
-
# Like RubyVM::
|
124
|
+
# Like RubyVM::Frame.new(thread_object), but has additional information
|
125
125
|
# available.
|
126
126
|
#
|
127
|
-
# === RubyVM::
|
127
|
+
# === RubyVM::Frame#iseq
|
128
128
|
# tf.iseq() -> ISeq
|
129
129
|
#
|
130
130
|
# Returns an instruction sequence object from the instruction sequence
|
131
|
-
# found inside the +
|
131
|
+
# found inside the +Frame+ object or +nil+ if there is none.
|
132
132
|
# But if iseq is +nil+ and tf.type is not C, +binding+, and
|
133
133
|
# +instruction_offset+, and +source_location+ are probably meaningless
|
134
134
|
# and will be +nil+ as well.
|
135
135
|
#
|
136
136
|
#
|
137
|
-
# === RubyVM::
|
137
|
+
# === RubyVM::Frame#instruction_offset
|
138
138
|
# tf.instruction_offset -> Fixnum
|
139
139
|
# Offset inside ISeq of instruction that the frame is currently on.
|
140
140
|
#
|
141
|
-
# === RubyVM::
|
141
|
+
# === RubyVM::Frame#instruction_offset=
|
142
142
|
#
|
143
143
|
# tf.instruction_offset=(Fixnum)
|
144
144
|
# Sets the threadframe to a new offset. Some restrictions may apply, e.g.
|
@@ -147,7 +147,7 @@
|
|
147
147
|
#
|
148
148
|
# <em>Don't need to implement initially.</em>
|
149
149
|
#
|
150
|
-
# === RubyVM::
|
150
|
+
# === RubyVM::Frame#return_changed?
|
151
151
|
# tf.return_changed?() -> boolean
|
152
152
|
#
|
153
153
|
# Returns true if tf _may_ be part of tail recursion removal so when
|
@@ -160,4 +160,4 @@
|
|
160
160
|
# = THANKS
|
161
161
|
#
|
162
162
|
# Martin Davis for suggesting
|
163
|
-
# RubyVM::
|
163
|
+
# RubyVM::Frame#new == Thread::current.threadframe
|
metadata
CHANGED
@@ -1,33 +1,29 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: rb-threadframe
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
6
|
-
- 0
|
7
|
-
- 39
|
8
|
-
version: "0.39"
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.40'
|
5
|
+
prerelease:
|
9
6
|
platform: ruby
|
10
|
-
authors:
|
7
|
+
authors:
|
11
8
|
- R. Bernstein
|
12
9
|
autorequire:
|
13
10
|
bindir: bin
|
14
11
|
cert_chain: []
|
15
|
-
|
16
|
-
date: 2011-10-27 00:00:00 -04:00
|
17
|
-
default_executable:
|
12
|
+
date: 2012-11-25 00:00:00.000000000 Z
|
18
13
|
dependencies: []
|
14
|
+
description: ! '
|
15
|
+
|
16
|
+
rb-threadframe gives introspection access for frames of a thread.
|
19
17
|
|
20
|
-
|
21
|
-
rb-threadframe gives introspection access for frames of a thread.\n"
|
18
|
+
'
|
22
19
|
email: rockyb@rubyforge.net
|
23
20
|
executables: []
|
24
|
-
|
25
|
-
extensions:
|
21
|
+
extensions:
|
26
22
|
- ext/extconf.rb
|
27
|
-
extra_rdoc_files:
|
23
|
+
extra_rdoc_files:
|
28
24
|
- README.md
|
29
25
|
- threadframe.rd
|
30
|
-
files:
|
26
|
+
files:
|
31
27
|
- README.md
|
32
28
|
- Rakefile
|
33
29
|
- Makefile
|
@@ -40,78 +36,56 @@ files:
|
|
40
36
|
- include/vm_core_mini.h
|
41
37
|
- lib/iseq_extra.rb
|
42
38
|
- lib/thread_frame.rb
|
43
|
-
- ext/
|
44
|
-
- ext/
|
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
|
51
|
-
- ext/thread_extra.h
|
52
|
-
- ext/iseq_extra.h
|
53
|
-
- ext/iseq_mini.h
|
39
|
+
- ext/1.9.3/thread_frame.c
|
40
|
+
- ext/version.h
|
54
41
|
- test/unit/test-trace.rb
|
55
42
|
- test/unit/test-iseq-save.rb
|
56
43
|
- test/unit/test-prev.rb
|
57
44
|
- test/unit/test-source.rb
|
58
45
|
- test/unit/test-lib-iseq.rb
|
59
46
|
- test/unit/test-return-stop.rb
|
47
|
+
- test/unit/test-frame.rb
|
60
48
|
- test/unit/test-proc.rb
|
61
49
|
- test/unit/test-invalid.rb
|
62
50
|
- test/unit/test-argc.rb
|
63
51
|
- test/unit/cfunc-use.rb
|
64
52
|
- test/unit/test-binding.rb
|
65
53
|
- test/unit/test-lib-iseq-extra.rb
|
66
|
-
- test/unit/test-thread.rb
|
67
54
|
- test/unit/test-iseq-brkpt.rb
|
68
55
|
- test/unit/test-iseq.rb
|
69
56
|
- test/unit/test-thread-trace-masks.rb
|
70
57
|
- test/unit/test-settracefunc.rb
|
71
58
|
- test/unit/test-sp-size.rb
|
72
|
-
- test/ruby/test_disasm.rb
|
73
|
-
- test/ruby/test_iseq.rb
|
74
|
-
- test/ruby/test_brkpt.rb
|
75
59
|
- test/ruby/test_tracefunc_adds.rb
|
76
|
-
- test/ruby/test_tracefunc_raise.rb
|
77
60
|
- threadframe.rd
|
78
61
|
- ext/extconf.rb
|
79
|
-
has_rdoc: true
|
80
62
|
homepage: http://github.com/rocky/rb-threadframe/tree/master
|
81
|
-
licenses:
|
63
|
+
licenses:
|
82
64
|
- MIT
|
83
65
|
post_install_message:
|
84
|
-
rdoc_options:
|
66
|
+
rdoc_options:
|
85
67
|
- --main
|
86
68
|
- README.md
|
87
69
|
- --title
|
88
|
-
- ThreadFrame 0.
|
89
|
-
require_paths:
|
70
|
+
- ThreadFrame 0.40 Documentation
|
71
|
+
require_paths:
|
90
72
|
- lib
|
91
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
73
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
92
74
|
none: false
|
93
|
-
requirements:
|
94
|
-
- -
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
|
97
|
-
|
98
|
-
- 9
|
99
|
-
- 2frame
|
100
|
-
version: 1.9.2frame
|
101
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - ! '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
102
80
|
none: false
|
103
|
-
requirements:
|
104
|
-
- -
|
105
|
-
- !ruby/object:Gem::Version
|
106
|
-
|
107
|
-
- 0
|
108
|
-
version: "0"
|
81
|
+
requirements:
|
82
|
+
- - ! '>='
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
109
85
|
requirements: []
|
110
|
-
|
111
86
|
rubyforge_project:
|
112
|
-
rubygems_version: 1.
|
87
|
+
rubygems_version: 1.8.23
|
113
88
|
signing_key:
|
114
89
|
specification_version: 3
|
115
90
|
summary: Frame introspection
|
116
91
|
test_files: []
|
117
|
-
|
data/ext/iseq_extra.c
DELETED
@@ -1,441 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
* Copyright (C) 2010 Rocky Bernstein
|
3
|
-
*/
|
4
|
-
#if 0 /* The following is to fake out rdoc, until I find a better fix. */
|
5
|
-
/*
|
6
|
-
* Additions to the RubyVM::InstructionSequence class
|
7
|
-
*/
|
8
|
-
VALUE rb_cIseq = rb_define_class_under(rb_cRubyVM, "InstructionSequence",
|
9
|
-
rb_cObject);
|
10
|
-
#endif
|
11
|
-
|
12
|
-
#include "../include/vm_core_mini.h" /* Pulls in ruby.h and node.h */
|
13
|
-
#include "iseq_mini.h" /* Pulls in ruby.h */
|
14
|
-
#include "../include/ruby19_externs.h"
|
15
|
-
#include <string.h> /* For strlen() */
|
16
|
-
|
17
|
-
struct iseq_insn_info_entry {
|
18
|
-
unsigned short position;
|
19
|
-
unsigned short line_no;
|
20
|
-
unsigned short sp;
|
21
|
-
};
|
22
|
-
|
23
|
-
#define COMPILE_OPTS_BOOL_SET_HASH(FIELD) \
|
24
|
-
rb_hash_aset(hash_opts, rb_str_new2(#FIELD), \
|
25
|
-
(compile_opts->FIELD) ? Qtrue : Qfalse)
|
26
|
-
|
27
|
-
/*
|
28
|
-
* Document-method: RubyVM::InstructionSequence::compile_options
|
29
|
-
*
|
30
|
-
* call-seq:
|
31
|
-
* RubyVM::InstructionSequence#compile_options -> Hash
|
32
|
-
*
|
33
|
-
* Returns a hash of the compiler options used to create the
|
34
|
-
* instruction sequence.
|
35
|
-
*/
|
36
|
-
VALUE
|
37
|
-
iseq_compile_options(VALUE iseqval)
|
38
|
-
{
|
39
|
-
rb_iseq_t *iseq;
|
40
|
-
if (Qnil == iseqval) return Qnil;
|
41
|
-
else {
|
42
|
-
VALUE hash_opts = rb_hash_new();
|
43
|
-
rb_compile_option_t *compile_opts;
|
44
|
-
GetISeqPtr(iseqval, iseq);
|
45
|
-
if (!iseq->compile_data) return Qnil;
|
46
|
-
compile_opts = iseq->compile_data->option;
|
47
|
-
COMPILE_OPTS_BOOL_SET_HASH(inline_const_cache);
|
48
|
-
COMPILE_OPTS_BOOL_SET_HASH(peephole_optimization);
|
49
|
-
COMPILE_OPTS_BOOL_SET_HASH(tailcall_optimization);
|
50
|
-
COMPILE_OPTS_BOOL_SET_HASH(specialized_instruction);
|
51
|
-
COMPILE_OPTS_BOOL_SET_HASH(operands_unification);
|
52
|
-
COMPILE_OPTS_BOOL_SET_HASH(stack_caching);
|
53
|
-
COMPILE_OPTS_BOOL_SET_HASH(trace_instruction);
|
54
|
-
COMPILE_OPTS_BOOL_SET_HASH(debug_level);
|
55
|
-
COMPILE_OPTS_BOOL_SET_HASH(save_tree_node);
|
56
|
-
COMPILE_OPTS_BOOL_SET_HASH(save_compile_opts);
|
57
|
-
return hash_opts;
|
58
|
-
}
|
59
|
-
}
|
60
|
-
|
61
|
-
/*
|
62
|
-
* Document-method: RubyVM::InstructionSequence::encoded
|
63
|
-
*
|
64
|
-
* call-seq:
|
65
|
-
* RubyVM::InstructionSequence#iseq_encoded -> String
|
66
|
-
*
|
67
|
-
* Returns a string of the encoded bytes of the instruction
|
68
|
-
* sequence. Note that this is probably not usable as is, may be useful in
|
69
|
-
* decoding instructions (using other info) or for getting a sha1
|
70
|
-
* checksum.
|
71
|
-
*/
|
72
|
-
VALUE
|
73
|
-
iseq_iseq_encoded(VALUE iseqval)
|
74
|
-
{
|
75
|
-
rb_iseq_t *iseq;
|
76
|
-
GetISeqPtr(iseqval, iseq);
|
77
|
-
return rb_str_new((char *) iseq->iseq_encoded, iseq->iseq_size);
|
78
|
-
}
|
79
|
-
|
80
|
-
|
81
|
-
/*
|
82
|
-
* Document-method: RubyVM::InstructionSequence::equal?
|
83
|
-
*
|
84
|
-
* call-seq:
|
85
|
-
* RubyVM::InstructionSequence#equal?(iseq2) -> bool
|
86
|
-
*
|
87
|
-
* Returns true if the instruction sequences are equal.
|
88
|
-
*/
|
89
|
-
VALUE
|
90
|
-
iseq_equal(VALUE iseqval1, VALUE iseqval2)
|
91
|
-
{
|
92
|
-
rb_iseq_t *iseq1, *iseq2;
|
93
|
-
|
94
|
-
if (Qnil == iseqval2) return Qfalse;
|
95
|
-
if (!rb_obj_is_kind_of(iseqval2, rb_cISeq)) {
|
96
|
-
rb_raise(rb_eTypeError,
|
97
|
-
"comparison argument must be an instance of %s or nil (is %s)",
|
98
|
-
rb_obj_classname(iseqval1), rb_obj_classname(iseqval2));
|
99
|
-
}
|
100
|
-
|
101
|
-
if (iseqval1 == iseqval2) return Qtrue;
|
102
|
-
GetISeqPtr(iseqval1, iseq1);
|
103
|
-
GetISeqPtr(iseqval2, iseq2);
|
104
|
-
|
105
|
-
/* FIXME: the count 28 below is bogus. I think this should be the fields
|
106
|
-
from "type" to "mark_ary". Should also include iseq->encoded.
|
107
|
-
*/
|
108
|
-
if (0 == memcmp(iseq1, iseq2, 28))
|
109
|
-
return Qtrue;
|
110
|
-
else
|
111
|
-
return Qfalse;
|
112
|
-
}
|
113
|
-
|
114
|
-
VALUE
|
115
|
-
iseq_parent(VALUE self)
|
116
|
-
{
|
117
|
-
rb_iseq_t *piseq;
|
118
|
-
rb_iseq_t *parent_iseq;
|
119
|
-
VALUE parent_iseqval;
|
120
|
-
GetISeqPtr(self, piseq);
|
121
|
-
|
122
|
-
if (!RTEST(piseq->parent_iseq)) return Qnil;
|
123
|
-
parent_iseqval = iseq_alloc_shared(rb_cISeq);
|
124
|
-
GetISeqPtr(parent_iseqval, parent_iseq);
|
125
|
-
memcpy(parent_iseq, piseq->parent_iseq, sizeof(struct rb_iseq_struct));
|
126
|
-
return parent_iseqval;
|
127
|
-
}
|
128
|
-
|
129
|
-
VALUE
|
130
|
-
iseq_local_iseq(VALUE self)
|
131
|
-
{
|
132
|
-
rb_iseq_t *piseq;
|
133
|
-
rb_iseq_t *local_iseq;
|
134
|
-
VALUE local_iseqval;
|
135
|
-
GetISeqPtr(self, piseq);
|
136
|
-
|
137
|
-
if (!RTEST(piseq->local_iseq)) return Qnil;
|
138
|
-
local_iseqval = iseq_alloc_shared(rb_cISeq);
|
139
|
-
GetISeqPtr(local_iseqval, local_iseq);
|
140
|
-
memcpy(local_iseq, piseq->local_iseq, sizeof(struct rb_iseq_struct));
|
141
|
-
return local_iseqval;
|
142
|
-
}
|
143
|
-
|
144
|
-
/*
|
145
|
-
* call-seq:
|
146
|
-
* RubyVM::InstructionSequence#local_name(i) - String
|
147
|
-
*
|
148
|
-
* Returns the string name of local variable in i'th position
|
149
|
-
* of the instruction sequence local table, or nil if i is
|
150
|
-
* out of range.
|
151
|
-
*/
|
152
|
-
VALUE
|
153
|
-
iseq_local_name(VALUE iseqval, VALUE val)
|
154
|
-
{
|
155
|
-
rb_iseq_t *iseq;
|
156
|
-
if (FIXNUM_P(val)) {
|
157
|
-
long int i = FIX2INT(val);
|
158
|
-
long int size;
|
159
|
-
|
160
|
-
GetISeqPtr(iseqval, iseq);
|
161
|
-
|
162
|
-
size = iseq->local_table_size;
|
163
|
-
|
164
|
-
if (i < 0) i = size + i;
|
165
|
-
|
166
|
-
if (i >= size)
|
167
|
-
rb_raise(rb_eIndexError,
|
168
|
-
"local table index %ld should be in the range -%ld .. %ld",
|
169
|
-
i, size, size-1);
|
170
|
-
|
171
|
-
return rb_str_new2(rb_id2name(iseq->local_table[i]));
|
172
|
-
} else {
|
173
|
-
rb_raise(rb_eTypeError, "type mismatch: %s given, Fixnum expected",
|
174
|
-
rb_class2name(CLASS_OF(val)));
|
175
|
-
}
|
176
|
-
/* not reached. */
|
177
|
-
return Qnil;
|
178
|
-
}
|
179
|
-
|
180
|
-
/*
|
181
|
-
* call-seq:
|
182
|
-
* RubyVM::InstructionSequence#name -> String
|
183
|
-
*
|
184
|
-
* Returns the name if the instruction sequence.
|
185
|
-
*/
|
186
|
-
VALUE
|
187
|
-
iseq_name(VALUE iseqval)
|
188
|
-
{
|
189
|
-
rb_iseq_t *iseq;
|
190
|
-
GetISeqPtr(iseqval, iseq);
|
191
|
-
return(iseq->name);
|
192
|
-
}
|
193
|
-
|
194
|
-
/*
|
195
|
-
* call-seq:
|
196
|
-
* RubyVM::InstructionSequence#offsetlines -> Hash[Fixnum] -> [Fixnum]
|
197
|
-
*
|
198
|
-
* Returns an hash. The keys in the hash form the VM offsets of the
|
199
|
-
* instructions. The value of the hash for a given offset is a list
|
200
|
-
* of line numbers associated with that offset.
|
201
|
-
*/
|
202
|
-
VALUE iseq_offsetlines(VALUE iseqval)
|
203
|
-
{
|
204
|
-
rb_iseq_t *iseq;
|
205
|
-
VALUE offsetlines = rb_hash_new();
|
206
|
-
unsigned long i, size;
|
207
|
-
struct iseq_insn_info_entry *table;
|
208
|
-
|
209
|
-
GetISeqPtr(iseqval, iseq);
|
210
|
-
|
211
|
-
size = iseq->insn_info_size;
|
212
|
-
table = iseq->insn_info_table;
|
213
|
-
|
214
|
-
for (i = 0; i < size; i++) {
|
215
|
-
VALUE ary = rb_ary_new2(1);
|
216
|
-
rb_ary_push(ary, INT2FIX(table[i].line_no));
|
217
|
-
rb_hash_aset(offsetlines, INT2FIX(table[i].position), ary);
|
218
|
-
}
|
219
|
-
return offsetlines;
|
220
|
-
}
|
221
|
-
|
222
|
-
/*
|
223
|
-
* call-seq:
|
224
|
-
* RubyVM::InstructionSequence#offset2lines(offset) -> [Fixnum]
|
225
|
-
*
|
226
|
-
* Returns an Array or nil. If offset is found then return the list of
|
227
|
-
* lines associated with that offset. If the offset isn't found return nil.
|
228
|
-
*/
|
229
|
-
VALUE iseq_offset2lines(VALUE iseqval, VALUE offsetval)
|
230
|
-
{
|
231
|
-
rb_iseq_t *iseq;
|
232
|
-
|
233
|
-
GetISeqPtr(iseqval, iseq);
|
234
|
-
|
235
|
-
if (FIXNUM_P(offsetval)) {
|
236
|
-
unsigned long i, size;
|
237
|
-
int offset = FIX2INT(offsetval);
|
238
|
-
struct iseq_insn_info_entry *table;
|
239
|
-
|
240
|
-
size = iseq->insn_info_size;
|
241
|
-
table = iseq->insn_info_table;
|
242
|
-
|
243
|
-
for (i = 0; i < size; i++) {
|
244
|
-
if (table[i].position == offset) {
|
245
|
-
VALUE ary = rb_ary_new2(1);
|
246
|
-
rb_ary_push(ary, INT2FIX(table[i].line_no));
|
247
|
-
return ary;
|
248
|
-
}
|
249
|
-
}
|
250
|
-
}
|
251
|
-
return Qnil;
|
252
|
-
}
|
253
|
-
|
254
|
-
/* FIXME: should return array of destroyed entries */
|
255
|
-
VALUE iseq_killcache(VALUE iseqval)
|
256
|
-
{
|
257
|
-
rb_iseq_t *iseqdat;
|
258
|
-
VALUE *iseq ;
|
259
|
-
unsigned long i, size, count = 0;
|
260
|
-
struct iseq_insn_info_entry *table;
|
261
|
-
|
262
|
-
GetISeqPtr(iseqval, iseqdat);
|
263
|
-
iseq = iseqdat->iseq;
|
264
|
-
size = iseqdat->insn_info_size;
|
265
|
-
table = iseqdat->insn_info_table;
|
266
|
-
for (i = 0; i < size; i++) {
|
267
|
-
const unsigned long pos = table[i].position;
|
268
|
-
const VALUE insn = iseq[pos];
|
269
|
-
if (0 == strncmp(insn_name(insn), "getinlinecache",
|
270
|
-
sizeof("getinlinecache")))
|
271
|
-
{
|
272
|
-
/* printf("pos: %lu\n", pos); */
|
273
|
-
count ++;
|
274
|
-
iseq[pos] = 0;
|
275
|
-
iseq[pos+1] = 0;
|
276
|
-
iseq[pos+2] = 0;
|
277
|
-
}
|
278
|
-
}
|
279
|
-
return INT2FIX(count);
|
280
|
-
}
|
281
|
-
|
282
|
-
const char *
|
283
|
-
source_container_type(VALUE fileval)
|
284
|
-
{
|
285
|
-
const char *filename = RSTRING_PTR(fileval);
|
286
|
-
size_t len = strlen(filename);
|
287
|
-
|
288
|
-
/* FIXME: Looking for (...) is a hack that I would love to know how
|
289
|
-
to remove. Probably Ruby has to be changed to record this kind
|
290
|
-
of information.
|
291
|
-
*/
|
292
|
-
if (len > 0 &&
|
293
|
-
((filename[0] == '(' && filename[len-1] == ')')
|
294
|
-
|| 0 == strncmp(filename, "<compiled>",
|
295
|
-
sizeof("<compiled>"))))
|
296
|
-
return "string";
|
297
|
-
else
|
298
|
-
return "file";
|
299
|
-
}
|
300
|
-
|
301
|
-
|
302
|
-
VALUE
|
303
|
-
iseq_source_container_internal(rb_iseq_t *iseq)
|
304
|
-
{
|
305
|
-
VALUE fileval = iseq->filename;
|
306
|
-
const char *contain_type = source_container_type(fileval);
|
307
|
-
|
308
|
-
return rb_ary_new3(2, rb_str_new2(contain_type), fileval);
|
309
|
-
}
|
310
|
-
|
311
|
-
/*
|
312
|
-
* call-seq:
|
313
|
-
* RubyVM::InstructionSequence#source_container() -> [Type, String]
|
314
|
-
*
|
315
|
-
* Returns a tuple representing kind of container, e.g. file
|
316
|
-
* eval'd string object, and the name of the container. If file,
|
317
|
-
* it would be a file name. If an eval'd string it might be the string.
|
318
|
-
*/
|
319
|
-
static VALUE
|
320
|
-
iseq_source_container(VALUE iseqval)
|
321
|
-
{
|
322
|
-
rb_iseq_t *iseq;
|
323
|
-
|
324
|
-
if (Qnil == iseqval) return Qnil;
|
325
|
-
GetISeqPtr(iseqval, iseq);
|
326
|
-
return iseq_source_container_internal(iseq);
|
327
|
-
}
|
328
|
-
|
329
|
-
|
330
|
-
#if 0
|
331
|
-
/*
|
332
|
-
* call-seq:
|
333
|
-
* RubyVM::InstructionSequence#type() -> Fixnum
|
334
|
-
*
|
335
|
-
* Returns instruction-sequence type.
|
336
|
-
*/
|
337
|
-
static VALUE
|
338
|
-
iseq_type(VALUE iseqval)
|
339
|
-
#endif
|
340
|
-
|
341
|
-
#define ISEQ_FIELD_METHOD(FIELD) \
|
342
|
-
static VALUE \
|
343
|
-
iseq_##FIELD(VALUE iseqval) \
|
344
|
-
{ \
|
345
|
-
rb_iseq_t *iseq; \
|
346
|
-
if (Qnil == iseqval) return Qnil; \
|
347
|
-
GetISeqPtr(iseqval, iseq); \
|
348
|
-
return iseq->FIELD; \
|
349
|
-
}
|
350
|
-
|
351
|
-
ISEQ_FIELD_METHOD(orig) ;
|
352
|
-
ISEQ_FIELD_METHOD(self) ;
|
353
|
-
ISEQ_FIELD_METHOD(type) ;
|
354
|
-
|
355
|
-
#define ISEQ_INT_FIELD_METHOD(FIELD) \
|
356
|
-
extern VALUE \
|
357
|
-
iseq_##FIELD(VALUE iseqval) \
|
358
|
-
{ \
|
359
|
-
rb_iseq_t *iseq; \
|
360
|
-
GetISeqPtr(iseqval, iseq); \
|
361
|
-
return INT2FIX(iseq->FIELD); \
|
362
|
-
}
|
363
|
-
|
364
|
-
ISEQ_INT_FIELD_METHOD(arg_block) ;
|
365
|
-
ISEQ_INT_FIELD_METHOD(arg_opts) ;
|
366
|
-
ISEQ_INT_FIELD_METHOD(arg_post_len) ;
|
367
|
-
ISEQ_INT_FIELD_METHOD(arg_rest) ;
|
368
|
-
ISEQ_INT_FIELD_METHOD(arg_simple) ;
|
369
|
-
ISEQ_INT_FIELD_METHOD(argc) ;
|
370
|
-
ISEQ_INT_FIELD_METHOD(iseq_size) ;
|
371
|
-
ISEQ_INT_FIELD_METHOD(klass) ;
|
372
|
-
ISEQ_INT_FIELD_METHOD(line_no) ;
|
373
|
-
ISEQ_INT_FIELD_METHOD(local_size) ;
|
374
|
-
ISEQ_INT_FIELD_METHOD(local_table_size) ;
|
375
|
-
|
376
|
-
/*
|
377
|
-
* call-seq:
|
378
|
-
* RubyVM::InstructionSequence#line_range() -> Range
|
379
|
-
*
|
380
|
-
* Returns a range containing the starting line number and the
|
381
|
-
* ending line of the source code for the instruction-sequence.
|
382
|
-
*/
|
383
|
-
static VALUE
|
384
|
-
iseq_line_range(VALUE iseqval)
|
385
|
-
{
|
386
|
-
rb_iseq_t *iseq;
|
387
|
-
|
388
|
-
GetISeqPtr(iseqval, iseq);
|
389
|
-
if (Qnil == iseqval) return Qnil;
|
390
|
-
else {
|
391
|
-
unsigned long i, size = iseq->insn_info_size;
|
392
|
-
struct iseq_insn_info_entry *table = iseq->insn_info_table;
|
393
|
-
unsigned short min_line = table[0].line_no;
|
394
|
-
unsigned short max_line = table[0].line_no;
|
395
|
-
|
396
|
-
for (i = 0; i < size; i++) {
|
397
|
-
if (table[i].line_no < min_line)
|
398
|
-
min_line = table[i].line_no;
|
399
|
-
else if (table[i].line_no > max_line)
|
400
|
-
max_line = table[i].line_no;
|
401
|
-
}
|
402
|
-
return rb_range_new(INT2FIX(min_line), INT2FIX(max_line), 0);
|
403
|
-
}
|
404
|
-
}
|
405
|
-
|
406
|
-
|
407
|
-
/* RDoc can't find methods when we use a definition like this: */
|
408
|
-
#define RB_DEFINE_ISEQ_METHOD(FIELD, ARGC) \
|
409
|
-
rb_define_method(rb_cISeq, #FIELD, iseq_##FIELD, ARGC);
|
410
|
-
|
411
|
-
void
|
412
|
-
Init_iseq_extra(void)
|
413
|
-
{
|
414
|
-
rb_define_method(rb_cISeq, "arg_block", iseq_arg_block, 0) ;
|
415
|
-
rb_define_method(rb_cISeq, "arg_opts", iseq_arg_opts, 0) ;
|
416
|
-
rb_define_method(rb_cISeq, "arg_post_len", iseq_arg_post_len, 0) ;
|
417
|
-
rb_define_method(rb_cISeq, "arg_rest", iseq_arg_rest, 0) ;
|
418
|
-
rb_define_method(rb_cISeq, "arg_simple", iseq_arg_simple, 0) ;
|
419
|
-
rb_define_method(rb_cISeq, "argc", iseq_argc, 0) ;
|
420
|
-
rb_define_method(rb_cISeq, "compile_options", iseq_compile_options, 0) ;
|
421
|
-
rb_define_method(rb_cISeq, "equal?", iseq_equal, 1) ;
|
422
|
-
rb_define_method(rb_cISeq, "encoded", iseq_iseq_encoded, 0) ;
|
423
|
-
rb_define_method(rb_cISeq, "iseq_size", iseq_iseq_size, 0) ;
|
424
|
-
rb_define_method(rb_cISeq, "killcache", iseq_killcache, 0) ;
|
425
|
-
rb_define_method(rb_cISeq, "klass", iseq_klass, 0) ;
|
426
|
-
rb_define_method(rb_cISeq, "lineno", iseq_line_no, 0) ;
|
427
|
-
rb_define_method(rb_cISeq, "line_range", iseq_line_range, 0) ;
|
428
|
-
rb_define_method(rb_cISeq, "local_iseq", iseq_local_iseq, 0) ;
|
429
|
-
rb_define_method(rb_cISeq, "local_name", iseq_local_name, 1) ;
|
430
|
-
rb_define_method(rb_cISeq, "local_size", iseq_local_size, 0) ;
|
431
|
-
rb_define_method(rb_cISeq, "local_table_size", iseq_local_table_size, 0) ;
|
432
|
-
rb_define_method(rb_cISeq, "offset2lines", iseq_offset2lines, 1) ;
|
433
|
-
rb_define_method(rb_cISeq, "offsetlines", iseq_offsetlines, 0) ;
|
434
|
-
rb_define_method(rb_cISeq, "orig", iseq_orig, 0) ;
|
435
|
-
rb_define_method(rb_cISeq, "parent", iseq_parent, 0) ;
|
436
|
-
rb_define_method(rb_cISeq, "name", iseq_name, 0) ;
|
437
|
-
rb_define_method(rb_cISeq, "self", iseq_self, 0) ;
|
438
|
-
rb_define_method(rb_cISeq, "source_container", iseq_source_container, 0) ;
|
439
|
-
rb_define_method(rb_cISeq, "type", iseq_type, 0) ;
|
440
|
-
|
441
|
-
}
|