sender 1.5.9 → 1.5.10
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|