sender 1.5.9 → 1.5.10
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/README.rdoc +278 -278
- data/ext/sender/RPSender_internal.c +23 -23
- data/ext/sender/RPSender_internal.h +9 -9
- data/ext/sender/RubySourceSupport.c +20 -20
- data/ext/sender/RubySourceSupport.h +65 -65
- data/ext/sender/extconf.rb +4 -4
- data/ext/sender/rb_Global.c +107 -107
- data/ext/sender/rb_Global.h +6 -6
- data/ext/sender/rb_Global_internal.h +4 -4
- data/ext/sender/rb_Kernel.c +556 -556
- data/ext/sender/rb_Kernel.h +24 -24
- data/ext/sender/rb_Kernel_internal.h +5 -5
- data/ext/sender/sender.c +6 -6
- metadata +68 -70
@@ -6,32 +6,32 @@
|
|
6
6
|
* framePriorTo *
|
7
7
|
*****************/
|
8
8
|
|
9
|
-
rb_control_frame_t* RPRuby_internal_framePriorTo( rb_control_frame_t* c_control_frame )
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
9
|
+
rb_control_frame_t* RPRuby_internal_framePriorTo( rb_control_frame_t* c_control_frame ) {
|
10
|
+
|
11
|
+
rb_thread_t* c_thread = (rb_thread_t *)RTYPEDDATA_DATA(rb_thread_current());
|
12
|
+
rb_control_frame_t* c_prior_control_frame = NULL;
|
13
|
+
// get the current frame pointer
|
14
|
+
if ( c_control_frame == NULL ) {
|
15
|
+
c_control_frame = c_thread->cfp;
|
16
|
+
}
|
17
|
+
|
18
18
|
if ( ( c_prior_control_frame = rb_vm_get_ruby_level_next_cfp( c_thread, c_control_frame ) ) != 0) {
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
|
20
|
+
// not sure why we have to call this a second time after it was called at the end of rb_vm_get_ruby_level_next_cfp,
|
21
|
+
// but for some reason it seems to be necessary
|
22
|
+
c_prior_control_frame = RUBY_VM_PREVIOUS_CONTROL_FRAME( c_prior_control_frame );
|
23
23
|
|
24
24
|
}
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
25
|
+
else {
|
26
|
+
c_prior_control_frame = NULL;
|
27
|
+
}
|
28
|
+
|
29
|
+
// if we have a nil object we've passed main, we're done
|
30
|
+
if ( c_prior_control_frame->self == Qnil ) {
|
31
|
+
return NULL;
|
32
|
+
}
|
33
33
|
|
34
|
-
|
35
|
-
|
34
|
+
return c_prior_control_frame;
|
35
|
+
|
36
36
|
}
|
37
37
|
|
@@ -1,15 +1,15 @@
|
|
1
1
|
#ifndef RP_SENDER_INTERNAL
|
2
|
-
|
2
|
+
#define RP_SENDER_INTERNAL
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
#include "ruby.h"
|
5
|
+
#include "eval_intern.h"
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
typedef enum BOOL_e {
|
8
|
+
FALSE,
|
9
|
+
TRUE
|
10
|
+
} BOOL;
|
11
11
|
|
12
|
-
|
13
|
-
|
12
|
+
rb_control_frame_t* RPRuby_internal_framePriorTo( rb_control_frame_t* control_frame );
|
13
|
+
VALUE RPSender_internal_backtraceHashForControlFrame( const rb_control_frame_t* c_top_of_control_frame );
|
14
14
|
|
15
15
|
#endif
|
@@ -6,27 +6,27 @@
|
|
6
6
|
|
7
7
|
#include "iseq.h"
|
8
8
|
|
9
|
-
//
|
10
|
-
//
|
11
|
-
//
|
9
|
+
// Taken from eval.c in Ruby source
|
10
|
+
// No header, so easiest way to integrate was to copy the code and make my own header.
|
11
|
+
// Previously declared static; otherwise unchanged
|
12
12
|
|
13
13
|
int rb_vm_get_sourceline(const rb_control_frame_t *cfp)
|
14
14
|
{
|
15
15
|
int line_no = 0;
|
16
16
|
const rb_iseq_t *iseq = cfp->iseq;
|
17
|
-
|
17
|
+
|
18
18
|
if (RUBY_VM_NORMAL_ISEQ_P(iseq)) {
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
19
|
+
rb_num_t i;
|
20
|
+
size_t pos = cfp->pc - cfp->iseq->iseq_encoded;
|
21
|
+
|
22
|
+
for (i = 0; i < iseq->insn_info_size; i++) {
|
23
|
+
if (iseq->insn_info_table[i].position == pos) {
|
24
|
+
if (i == 0) goto found;
|
25
|
+
line_no = iseq->insn_info_table[i - 1].line_no;
|
26
|
+
goto found;
|
27
|
+
}
|
28
|
+
}
|
29
|
+
line_no = iseq->insn_info_table[i - 1].line_no;
|
30
30
|
}
|
31
31
|
found:
|
32
32
|
return line_no;
|
@@ -35,13 +35,13 @@ found:
|
|
35
35
|
struct enumerator* enumerator_ptr(VALUE obj)
|
36
36
|
{
|
37
37
|
struct enumerator *ptr;
|
38
|
-
|
38
|
+
|
39
39
|
Data_Get_Struct(obj, struct enumerator, ptr);
|
40
|
-
|
41
|
-
|
42
|
-
|
40
|
+
|
41
|
+
// modified because a call to a local version of enumerator_mark won't verify
|
42
|
+
|
43
43
|
if (!ptr || ptr->obj == Qundef) {
|
44
|
-
|
44
|
+
rb_raise(rb_eArgError, "uninitialized enumerator");
|
45
45
|
}
|
46
46
|
return ptr;
|
47
47
|
}
|
@@ -1,77 +1,77 @@
|
|
1
1
|
#ifndef RP_SENDER_RUBY_SOURCE_SUPPORT
|
2
|
-
|
2
|
+
#define RP_SENDER_RUBY_SOURCE_SUPPORT
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
4
|
+
#include "ruby.h"
|
5
|
+
#include "eval_intern.h"
|
6
|
+
#include "version.h"
|
7
|
+
#if RUBY_PATCHLEVEL == -1
|
8
|
+
#include "vm_core.h"
|
9
|
+
#endif
|
10
|
+
#include "method.h"
|
11
11
|
|
12
|
-
|
12
|
+
#define MAX_POSBUF 128
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
enum context_type {
|
15
|
+
CONTINUATION_CONTEXT = 0,
|
16
|
+
FIBER_CONTEXT = 1,
|
17
|
+
ROOT_FIBER_CONTEXT = 2
|
18
|
+
};
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
20
|
+
typedef struct rb_context_struct {
|
21
|
+
enum context_type type;
|
22
|
+
VALUE self;
|
23
|
+
int argc;
|
24
|
+
VALUE value;
|
25
|
+
VALUE *vm_stack;
|
26
|
+
#ifdef CAPTURE_JUST_VALID_VM_STACK
|
27
|
+
int vm_stack_slen; /* length of stack (head of th->stack) */
|
28
|
+
int vm_stack_clen; /* length of control frames (tail of th->stack) */
|
29
|
+
#endif
|
30
|
+
VALUE *machine_stack;
|
31
|
+
VALUE *machine_stack_src;
|
32
|
+
#ifdef __ia64
|
33
|
+
VALUE *machine_register_stack;
|
34
|
+
VALUE *machine_register_stack_src;
|
35
|
+
int machine_register_stack_size;
|
36
|
+
#endif
|
37
|
+
rb_thread_t saved_thread;
|
38
|
+
rb_jmpbuf_t jmpbuf;
|
39
|
+
int machine_stack_size;
|
40
|
+
} rb_context_t;
|
41
41
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
42
|
+
enum fiber_status {
|
43
|
+
CREATED,
|
44
|
+
RUNNING,
|
45
|
+
TERMINATED
|
46
|
+
};
|
47
47
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
48
|
+
typedef struct rb_fiber_struct {
|
49
|
+
rb_context_t cont;
|
50
|
+
VALUE prev;
|
51
|
+
enum fiber_status status;
|
52
|
+
struct rb_fiber_struct *prev_fiber;
|
53
|
+
struct rb_fiber_struct *next_fiber;
|
54
|
+
} rb_fiber_t;
|
55
55
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
56
|
+
struct enumerator {
|
57
|
+
VALUE obj;
|
58
|
+
ID meth;
|
59
|
+
VALUE args;
|
60
|
+
VALUE fib;
|
61
|
+
VALUE dst;
|
62
|
+
VALUE no_next;
|
63
|
+
};
|
64
64
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
65
|
+
#define GetFiberPtr(obj, ptr) do {\
|
66
|
+
ptr = (rb_fiber_t*)DATA_PTR(obj);\
|
67
|
+
if (!ptr) rb_raise(rb_eFiberError, "uninitialized fiber");\
|
68
|
+
} while(0)
|
69
69
|
|
70
70
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
71
|
+
ID frame_func_id( rb_control_frame_t *cfp );
|
72
|
+
ID rb_frame_caller(void);
|
73
|
+
int rb_vm_get_sourceline(const rb_control_frame_t *cfp);
|
74
|
+
void control_frame_dump(rb_thread_t *th, rb_control_frame_t *cfp);
|
75
|
+
struct enumerator* enumerator_ptr(VALUE obj);
|
76
|
+
|
77
77
|
#endif
|
data/ext/sender/extconf.rb
CHANGED
@@ -5,7 +5,7 @@ require 'core-source'
|
|
5
5
|
|
6
6
|
target = "sender"
|
7
7
|
|
8
|
-
required_core_headers = [
|
8
|
+
required_core_headers = [ "vm_core.h",
|
9
9
|
"iseq.h",
|
10
10
|
"eval_intern.h",
|
11
11
|
"version.h" ]
|
@@ -14,7 +14,7 @@ default_cflags = "-march=x86-64 -g -fno-common -fsigned-char -pipe"
|
|
14
14
|
|
15
15
|
# Create our makefile from sources
|
16
16
|
if ensure_core_headers( required_core_headers )
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
with_cflags( default_cflags ) do
|
18
|
+
create_makefile( target )
|
19
|
+
end
|
20
20
|
end
|
data/ext/sender/rb_Global.c
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
#include "rb_Global.h"
|
3
3
|
#include "rb_Kernel.h"
|
4
4
|
|
5
|
-
//
|
5
|
+
// Internals from ruby that aren't included in the ruby lib
|
6
6
|
#include "RubySourceSupport.h"
|
7
7
|
|
8
8
|
#include "eval_intern.h"
|
@@ -11,16 +11,16 @@
|
|
11
11
|
* Global *
|
12
12
|
***********/
|
13
13
|
|
14
|
-
void Init_senderGlobal()
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
void Init_senderGlobal() {
|
15
|
+
|
16
|
+
rb_define_global_function( "__sender__", rb_RPRuby_Sender___sender__, 0 );
|
17
|
+
rb_define_global_function( "__caller__", rb_RPRuby_Sender___caller__, 0 );
|
18
18
|
|
19
19
|
}
|
20
20
|
|
21
21
|
/***************************************************************************************************************************************************************
|
22
22
|
****************************************************************************************************************************************************************
|
23
|
-
|
23
|
+
Ruby Global Methods
|
24
24
|
****************************************************************************************************************************************************************
|
25
25
|
***************************************************************************************************************************************************************/
|
26
26
|
|
@@ -34,54 +34,54 @@ void Init_senderGlobal() {
|
|
34
34
|
*
|
35
35
|
* Return object sending message to receiver.
|
36
36
|
*/
|
37
|
-
VALUE rb_RPRuby_Sender___sender__()
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
37
|
+
VALUE rb_RPRuby_Sender___sender__() {
|
38
|
+
|
39
|
+
// we want 3 levels of backtrace:
|
40
|
+
// 1: current call to __method__ (__method__ in context)
|
41
|
+
// 2: the frame we want, unless it is :new (call to context: __sender__)
|
42
|
+
// 3: the frame we want in the case #2 is :new
|
43
|
+
VALUE rb_backtrace_limit = INT2FIX( 3 );
|
44
|
+
|
45
|
+
VALUE rb_backtrace_array = rb_RPRuby_Sender_Kernel_backtrace( 1,
|
46
|
+
& rb_backtrace_limit,
|
47
|
+
rb_mKernel );
|
48
|
+
|
49
|
+
int c_backtrace_index = 1;
|
50
|
+
|
51
|
+
VALUE rb_backtrace_frame_hash = rb_ary_entry( rb_backtrace_array, c_backtrace_index );
|
52
|
+
|
53
|
+
VALUE rb_caller = rb_hash_aref( rb_backtrace_frame_hash,
|
54
|
+
ID2SYM( rb_intern( "method" ) ) );
|
55
|
+
|
56
|
+
// if we get :initialize as our caller and our __method__ is :initialize, we need to go up the chain
|
57
|
+
// until our caller is no longer :initialize or :new
|
58
|
+
while ( rb_caller == ID2SYM( rb_intern( "initialize" ) ) ) {
|
59
|
+
c_backtrace_index++;
|
60
|
+
rb_backtrace_frame_hash = rb_ary_entry( rb_backtrace_array, c_backtrace_index );
|
61
|
+
rb_caller = rb_hash_aref( rb_backtrace_frame_hash,
|
62
|
+
ID2SYM( rb_intern( "method" ) ) );
|
63
|
+
|
64
|
+
// we have one parent past our current method; if that is also :initialize, get the whole backtrace
|
65
|
+
if ( c_backtrace_index == 2 ) {
|
66
|
+
rb_backtrace_array = rb_RPRuby_Sender_Kernel_backtrace( 0, NULL, rb_mKernel );
|
67
|
+
}
|
68
|
+
}
|
69
|
+
|
70
|
+
// if we get "new" as our caller we need to get the next level, as we are in :initialize
|
71
|
+
// and want to know what called :new
|
72
|
+
//
|
73
|
+
// since we might have had to go up the chain from :initialize through parents before getting here we
|
74
|
+
// want to use a separate if statement
|
75
|
+
if ( rb_caller == ID2SYM( rb_intern( "new" ) ) ) {
|
76
|
+
c_backtrace_index++;
|
77
|
+
rb_backtrace_frame_hash = rb_ary_entry( rb_backtrace_array, c_backtrace_index );
|
78
|
+
}
|
79
|
+
|
80
|
+
VALUE rb_sender = rb_hash_aref( rb_backtrace_frame_hash,
|
81
|
+
ID2SYM( rb_intern( "object" ) ) );
|
82
|
+
|
83
|
+
// assuming we have a previous frame, return its rb_self (our current receiver's sender)
|
84
|
+
return rb_sender;
|
85
85
|
}
|
86
86
|
|
87
87
|
/***************
|
@@ -94,58 +94,58 @@ VALUE rb_RPRuby_Sender___sender__() {
|
|
94
94
|
*
|
95
95
|
* Return method sending message to receiver.
|
96
96
|
*/
|
97
|
-
VALUE rb_RPRuby_Sender___caller__()
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
97
|
+
VALUE rb_RPRuby_Sender___caller__() {
|
98
|
+
|
99
|
+
|
100
|
+
// we want 3 levels of backtrace:
|
101
|
+
// 1: current call to __method__ (__method__ in context)
|
102
|
+
// 2: the frame we want, unless it is :new (call to context: __sender__)
|
103
|
+
// 3: the frame we want in the case #2 is :new
|
104
|
+
VALUE rb_backtrace_limit = INT2FIX( 3 );
|
105
|
+
|
106
|
+
VALUE rb_backtrace_array = rb_RPRuby_Sender_Kernel_backtrace( 1,
|
107
|
+
& rb_backtrace_limit,
|
108
|
+
rb_mKernel );
|
109
|
+
|
110
|
+
int c_backtrace_index = 1;
|
111
|
+
|
112
|
+
VALUE rb_backtrace_frame_hash = rb_ary_entry( rb_backtrace_array, c_backtrace_index );
|
113
|
+
|
114
|
+
VALUE rb_caller = rb_hash_aref( rb_backtrace_frame_hash,
|
115
|
+
ID2SYM( rb_intern( "method" ) ) );
|
116
|
+
|
117
|
+
// we want to compare our caller as we go up the chain to our first caller to deal with super methods
|
118
|
+
// we have a symbol so no cloning is necessary (or appropriate)
|
119
|
+
VALUE rb_first_caller = rb_hash_aref( rb_ary_entry( rb_backtrace_array, 0 ),
|
120
|
+
ID2SYM( rb_intern( "method" ) ) );
|
121
|
+
|
122
|
+
// if we get :initialize as our caller and our __method__ is :initialize, we need to go up the chain
|
123
|
+
// until our caller is no longer :initialize or :new
|
124
|
+
while ( rb_caller == rb_first_caller ) {
|
125
|
+
c_backtrace_index++;
|
126
|
+
rb_backtrace_frame_hash = rb_ary_entry( rb_backtrace_array, c_backtrace_index );
|
127
|
+
rb_caller = rb_hash_aref( rb_backtrace_frame_hash,
|
128
|
+
ID2SYM( rb_intern( "method" ) ) );
|
129
|
+
|
130
|
+
// we have one parent past our current method; if that is also :initialize, get the whole backtrace
|
131
|
+
if ( c_backtrace_index == 2 ) {
|
132
|
+
rb_backtrace_array = rb_RPRuby_Sender_Kernel_backtrace( 0, NULL, rb_mKernel );
|
133
|
+
}
|
134
|
+
}
|
135
|
+
|
136
|
+
// if we get "new" as our caller we need to get the next level, as we are in :initialize
|
137
|
+
// and want to know what called :new
|
138
|
+
//
|
139
|
+
// since we might have had to go up the chain from :initialize through parents before getting here we
|
140
|
+
// want to use a separate if statement
|
141
|
+
if ( rb_caller == ID2SYM( rb_intern( "new" ) ) ) {
|
142
|
+
c_backtrace_index++;
|
143
|
+
rb_backtrace_frame_hash = rb_ary_entry( rb_backtrace_array, c_backtrace_index );
|
144
|
+
rb_caller = rb_hash_aref( rb_backtrace_frame_hash,
|
145
|
+
ID2SYM( rb_intern( "method" ) ) );
|
146
|
+
}
|
147
|
+
|
148
|
+
// assuming we have a previous frame, return its rb_self (our current receiver's sender)
|
149
|
+
return rb_caller;
|
150
150
|
}
|
151
151
|
|