rb-threadframe 0.39 → 0.40

Sign up to get free protection for your applications and to get access to all the features.
data/ext/proc_extra.c DELETED
@@ -1,186 +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::Proc classes
7
- */
8
- VALUE rb_cProc = rb_define_class("Proc", ...)
9
- #endif
10
-
11
- #include "../include/vm_core_mini.h" /* Pulls in ruby.h and node.h */
12
- #include "../include/ruby19_externs.h"
13
-
14
- struct METHOD {
15
- VALUE recv;
16
- VALUE rclass;
17
- ID id;
18
- rb_method_entry_t me;
19
- };
20
-
21
- /*
22
- * call-seq:
23
- * Proc#iseq -> RubyVM::InstructionSequence
24
- *
25
- * Returns the instruction sequence for a Proc object.
26
- */
27
- VALUE
28
- proc_iseq(VALUE self)
29
- {
30
- rb_proc_t *proc;
31
- rb_iseq_t *iseq;
32
- VALUE rb_iseq;
33
- GetProcPtr(self, proc);
34
- iseq = proc->block.iseq;
35
- if (!iseq
36
- #if 0
37
- /* Our iseq struct isn't complete enough to contain self. */
38
- || !RUBY_VM_NORMAL_ISEQ_P(iseq->self)
39
- #endif
40
- )
41
- return Qnil;
42
- rb_iseq = iseq_alloc_shared(rb_cISeq);
43
- RDATA(rb_iseq)->data = iseq;
44
- return rb_iseq;
45
- }
46
-
47
- /* Defined in Ruby 1.9 proc.c */
48
- extern rb_iseq_t *rb_method_get_iseq(VALUE method);
49
-
50
- #if 0 /* The following is to fake out rdoc, until I find a better fix. */
51
- /*
52
- * Additions to the RubyVM::Method and RubyVM::UnboundMethod class
53
- */
54
- VALUE rb_cIseq = rb_define_class("Method", ...)
55
- VALUE rb_cIseq = rb_define_class("UnboundMethod", ...)
56
- #endif
57
- /*
58
- * call-seq:
59
- * Method#iseq -> RubyVM::InstructionSequence
60
- *
61
- * Returns the instruction sequence of a Method object.
62
- */
63
- VALUE
64
- method_iseq(VALUE self)
65
- {
66
- VALUE rb_iseq;
67
- rb_iseq_t *iseq = rb_method_get_iseq(self);
68
- if (!iseq) return Qnil;
69
- rb_iseq = iseq_alloc_shared(rb_cISeq);
70
- RDATA(rb_iseq)->data = iseq;
71
- return rb_iseq;
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
-
146
- /*
147
- * call-seq:
148
- * Method#alias_count -> Fixnum
149
- *
150
- * number of aliases a method has
151
- */
152
- VALUE
153
- method_alias_count(VALUE self)
154
- {
155
- struct METHOD *m1 = (struct METHOD *)DATA_PTR(self);
156
- return INT2FIX(m1->me.def->alias_count);
157
- }
158
-
159
- /*
160
- * call-seq:
161
- * Method#original_id - Original name of method
162
- */
163
- VALUE
164
- method_original_id(VALUE self)
165
- {
166
- struct METHOD *m1 = (struct METHOD *)DATA_PTR(self);
167
- return ID2SYM(m1->me.def->original_id);
168
- }
169
-
170
-
171
- void
172
- Init_proc_extra(void)
173
- {
174
- /* Additions to Proc */
175
- rb_define_method(rb_cProc, "iseq", proc_iseq, 0);
176
-
177
- /* Additions to Method */
178
- rb_define_method(rb_cMethod, "alias_count", method_alias_count, 0);
179
- rb_define_method(rb_cMethod, "iseq", method_iseq, 0);
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);
186
- }
data/ext/proc_extra.h DELETED
@@ -1,3 +0,0 @@
1
- /* in proc_extra.c */
2
- extern VALUE proc_iseq(VALUE self);
3
- extern void Init_proc_extra(void);
data/ext/thread_extra.c DELETED
@@ -1,84 +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::Method class
7
- */
8
- VALUE rb_cThread = rb_define_class("Method", ...)
9
- #endif
10
-
11
- #include "../include/vm_core_mini.h" /* Pulls in ruby.h and node.h */
12
- #include "thread_extra.h"
13
-
14
- /*
15
- * call-seq:
16
- * Thread#exec_event_tracing -> bool
17
- *
18
- * Returns the value of the thread event-hook tracing.
19
- */
20
- VALUE
21
- thread_exec_event_tracing(VALUE self)
22
- {
23
- rb_thread_t *th;
24
- GetThreadPtr(self, th);
25
- return th->exec_event_tracing ? Qtrue : Qfalse;
26
- }
27
-
28
- /*
29
- * call-seq:
30
- * Thread#exec_event_tracing=(new_value)
31
- *
32
- * Sets the value of thread event-hook tracing.
33
- */
34
- VALUE
35
- thread_exec_event_tracing_set(VALUE self, VALUE new_value)
36
- {
37
- rb_thread_t *th;
38
- GetThreadPtr(self, th);
39
-
40
- th->exec_event_tracing = RTEST(new_value) ? Qtrue : Qfalse;
41
- return th->exec_event_tracing;
42
- }
43
-
44
- /*
45
- * call-seq:
46
- * Thread#tracing -> bool
47
- *
48
- * Returns the value of the thread event-hook tracing.
49
- */
50
- VALUE
51
- thread_tracing(VALUE self)
52
- {
53
- rb_thread_t *th;
54
- GetThreadPtr(self, th);
55
- return th->tracing ? Qtrue : Qfalse;
56
- }
57
-
58
- /*
59
- * call-seq:
60
- * Thread#tracing= bool
61
- *
62
- * Sets the value of thread event-hook tracing.
63
- */
64
- VALUE
65
- thread_tracing_set(VALUE self, VALUE new_value)
66
- {
67
- rb_thread_t *th;
68
- GetThreadPtr(self, th);
69
-
70
- th->tracing = RTEST(new_value) ? Qtrue : Qfalse;
71
- return th->tracing;
72
- }
73
-
74
- void
75
- Init_thread_extra(void)
76
- {
77
- /* Additions to Thread class */
78
- rb_define_method(rb_cThread, "exec_event_tracing=",
79
- thread_exec_event_tracing_set, 1);
80
- rb_define_method(rb_cThread, "exec_event_tracing",
81
- thread_exec_event_tracing, 0);
82
- rb_define_method(rb_cThread, "tracing=", thread_tracing_set, 1);
83
- rb_define_method(rb_cThread, "tracing", thread_tracing, 0);
84
- }
data/ext/thread_extra.h DELETED
@@ -1,5 +0,0 @@
1
- /* in thread_extra.c */
2
- extern VALUE thread_tracing(VALUE self);
3
- extern VALUE thread_set_tracing(VALUE self, VALUE new_value);
4
- extern void Init_thread_extra(void);
5
-
data/ext/thread_frame.c DELETED
@@ -1,1165 +0,0 @@
1
- /*
2
- * Copyright (C) 2010, 2011 Rocky Bernstein
3
- *
4
- * Access to Ruby's rb_control_frame_t and methods for working with that.
5
- * Things like getting a binding for a control frame.
6
- */
7
-
8
- /* What release we got? */
9
- #define THREADFRAME_VERSION "0.39"
10
-
11
- #include <string.h>
12
- #include "../include/vm_core_mini.h" /* Pulls in ruby.h and node.h */
13
- #include "proc_extra.h"
14
- #include "iseq_extra.h"
15
- #include "thread_extra.h"
16
-
17
- /* for GC debug */
18
-
19
- #ifndef RUBY_MARK_FREE_DEBUG
20
- #define RUBY_MARK_FREE_DEBUG 0
21
- #endif
22
-
23
- #if RUBY_MARK_FREE_DEBUG
24
- extern int ruby_gc_debug_indent;
25
-
26
- static void
27
- rb_gc_debug_indent(void)
28
- {
29
- printf("%*s", ruby_gc_debug_indent, "");
30
- }
31
-
32
- static void
33
- rb_gc_debug_body(const char *mode, const char *msg, int st, void *ptr)
34
- {
35
- if (st == 0) {
36
- ruby_gc_debug_indent--;
37
- }
38
- rb_gc_debug_indent();
39
- printf("%s: %s %s (%p)\n", mode, st ? "->" : "<-", msg, ptr);
40
-
41
- if (st) {
42
- ruby_gc_debug_indent++;
43
- }
44
-
45
- fflush(stdout);
46
- }
47
-
48
- #define RUBY_MARK_ENTER(msg) rb_gc_debug_body("mark", msg, 1, ptr)
49
- #define RUBY_MARK_LEAVE(msg) rb_gc_debug_body("mark", msg, 0, ptr)
50
- #define RUBY_FREE_ENTER(msg) rb_gc_debug_body("free", msg, 1, ptr)
51
- #define RUBY_FREE_LEAVE(msg) rb_gc_debug_body("free", msg, 0, ptr)
52
- #define RUBY_GC_INFO rb_gc_debug_indent(); printf
53
-
54
- #else
55
- #define RUBY_MARK_ENTER(msg)
56
- #define RUBY_MARK_LEAVE(msg)
57
- #define RUBY_FREE_ENTER(msg)
58
- #define RUBY_FREE_LEAVE(msg)
59
- #define RUBY_GC_INFO if(0)printf
60
- #endif
61
-
62
- /* Frames can't be detached from the control frame they live in.
63
- So we create a structure to contain the pair.
64
-
65
- The signature fields are used to weakly verify the validity of cfp.
66
- it stores to contents of fields in cfp on allocation. This, the
67
- validity of "th" pointing to a valid thread, and cfp pointing to valid
68
- location inside the frame area we use to check that this structure
69
- is valid. */
70
-
71
- typedef struct
72
- {
73
- rb_thread_t *th;
74
- rb_control_frame_t *cfp;
75
- VALUE *signature1[3]; /* iseq, flag, self */
76
- VALUE *signature2[1]; /* proc */
77
- } thread_frame_t;
78
-
79
- #include "../include/ruby19_externs.h"
80
-
81
- VALUE rb_cThreadFrame; /* ThreadFrame class */
82
- VALUE rb_eThreadFrameError; /* Error raised on invalid frames. */
83
-
84
- /* Static forward declarations */
85
- static VALUE thread_frame_iseq(VALUE klass);
86
- static VALUE thread_frame_prev_internal(rb_control_frame_t *prev_cfp,
87
- rb_thread_t *th, int n);
88
- static int thread_frame_stack_size_internal(rb_control_frame_t *cfp,
89
- rb_thread_t *th);
90
- static VALUE thread_frame_type(VALUE klass);
91
-
92
-
93
- extern void iseq_mark(void *ptr); /* in iseq.c */
94
-
95
- /*
96
- FIXME: I've never seen the following routine get called.
97
- Why?
98
- */
99
- static void
100
- thread_frame_mark(void *ptr)
101
- {
102
- RUBY_MARK_ENTER("thread_frame");
103
- if (ptr) {
104
- thread_frame_t *tf = ptr;
105
- if (tf && tf->cfp && RUBY_VM_NORMAL_ISEQ_P(tf->cfp->iseq)) {
106
- iseq_mark(tf->cfp->iseq);
107
- }
108
- }
109
- }
110
-
111
- static void
112
- tf_free(void *ptr)
113
- {
114
- thread_frame_t *tf;
115
- if (ptr) {
116
- tf = ptr;
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))
122
- tf->cfp->iseq->in_use--;
123
- xfree(ptr);
124
- }
125
- }
126
-
127
- /*
128
- Allocate a RubyVM::ThreadFrame used by new. Less common than
129
- thread_frame_t_alloc(). The caller is responsible for filling in
130
- the C struct data. Below we wrap NULL.
131
- */
132
- static VALUE
133
- thread_frame_alloc(VALUE klass)
134
- {
135
- return Data_Wrap_Struct(klass, thread_frame_mark, tf_free, NULL);
136
- }
137
-
138
- /*
139
- Allocate a RubyVM::ThreadFrame and set its threadframe structure.
140
- This is the more common allocate routine since one normally doesn't
141
- create a threadframe without <i>first</i> having something to put in it.
142
- */
143
- static thread_frame_t *
144
- thread_frame_t_alloc(VALUE tfval)
145
- {
146
- thread_frame_t *tf = ALLOC(thread_frame_t);
147
- memset(tf, 0, sizeof(thread_frame_t));
148
- DATA_PTR(tfval) = tf;
149
- return tf;
150
- }
151
-
152
- /*
153
- Check to see if tf is valid. +true+ is returned if we can't prove
154
- the frame is invalide. +nil+ or +false+ is returned if something is not
155
- right. In those cases where we don't know that we have a valid frame,
156
- we also NULL out the cfp if that hasn't been done already. This will
157
- keep garbage collection from marking bad data.
158
- */
159
- static VALUE
160
- thread_frame_invalid_internal(thread_frame_t *tf)
161
- {
162
- int cmp;
163
-
164
- /* All valid frame types have 0x1 set so we will use this.
165
- Warning: this is an undocumented assumption which may someday
166
- be wrong. */
167
- if (!tf->cfp) return Qtrue;
168
- if ((tf->cfp->flag & 0x1) == 0) {
169
- tf->cfp = NULL;
170
- return Qtrue;
171
- }
172
-
173
- if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(tf->th, tf->cfp)) {
174
- tf->cfp = NULL;
175
- return Qtrue;
176
- }
177
- if (RUBY_VM_NORMAL_ISEQ_P(tf->cfp->iseq)) {
178
- cmp = (0 == memcmp(tf->signature1, &(tf->cfp->iseq),
179
- sizeof(tf->signature1)) &&
180
- 0 == memcmp(tf->signature2, &(tf->cfp->proc),
181
- sizeof(tf->signature2)));
182
- if (cmp) return Qfalse;
183
- tf->cfp = NULL;
184
- return Qtrue;
185
- } else {
186
- /* FIXME: figure out what to do here. Probably more work is
187
- * needed in thread_frame_prev_internal.
188
- */
189
- return Qnil;
190
- }
191
- }
192
-
193
- /*
194
- COPY_SIGNATURE saves some invariant data from the frame for
195
- comparison later when the frame is used again.
196
-
197
- Even though fields like iseq may not be valid for things C function
198
- frames, nevertheless all we care about is whether they could change
199
- or not over the course of evaluation. Hving more data to compare
200
- against to verify whether a frame is valid is helpful. If the data
201
- is random unitialized data, that's even better. Again just so long as
202
- that random data doesn't change in the course of normal use.
203
-
204
- FIXME: There are probably more fields which could be saved. */
205
- #define COPY_SIGNATURE(tf, cfp) \
206
- memcpy(tf->signature1, &(cfp->iseq), sizeof(tf->signature1)); \
207
- memcpy(tf->signature2, &(cfp->proc), sizeof(tf->signature2))
208
-
209
- #define SAVE_FRAME(TF, TH) \
210
- tf->th = TH; \
211
- tf->cfp = thread_control_frame(tf->th); \
212
- tf->cfp->iseq->in_use++; \
213
- COPY_SIGNATURE(tf, tf->cfp); \
214
-
215
- #define GET_THREAD_PTR \
216
- rb_thread_t *th; \
217
- GetThreadPtr(thval, th)
218
-
219
-
220
- /*
221
- * call-seq:
222
- * RubyVM::ThreadFrame#threadframe -> thread_frame_object
223
- *
224
- * Returns a RubyVM::ThreadFrame object for the given thread.
225
- */
226
- static VALUE
227
- thread_frame_threadframe(VALUE thval)
228
- {
229
- thread_frame_t *tf = ALLOC(thread_frame_t);
230
- GET_THREAD_PTR;
231
- memset(tf, 0, sizeof(thread_frame_t));
232
- SAVE_FRAME(tf, th) ;
233
- return Data_Wrap_Struct(rb_cThreadFrame, thread_frame_mark, tf_free, tf);
234
- }
235
-
236
- #define THREAD_FRAME_SETUP \
237
- thread_frame_t *tf; \
238
- Data_Get_Struct(klass, thread_frame_t, tf)
239
-
240
- #define THREAD_FRAME_SETUP_WITH_ERROR \
241
- THREAD_FRAME_SETUP; \
242
- if (Qtrue == thread_frame_invalid_internal(tf)) \
243
- rb_raise(rb_eThreadFrameError, "invalid frame")
244
-
245
- #define THREAD_FRAME_FIELD_METHOD(FIELD) \
246
- static VALUE \
247
- thread_frame_##FIELD(VALUE klass) \
248
- { \
249
- THREAD_FRAME_SETUP ; \
250
- return tf->cfp->FIELD; \
251
- }
252
-
253
- #define THREAD_FRAME_FP_METHOD(REG) \
254
- VALUE \
255
- thread_frame_##REG(VALUE klass, VALUE index) \
256
- { \
257
- if (!FIXNUM_P(index)) { \
258
- rb_raise(rb_eTypeError, "integer argument expected"); \
259
- } else { \
260
- long int i = FIX2INT(index); \
261
- THREAD_FRAME_SETUP_WITH_ERROR ; \
262
- /* FIXME: check index is within range. */ \
263
- return tf->cfp->REG[-i]; /* stack grows "down" */ \
264
- } \
265
- }
266
-
267
- #if 0
268
- /*
269
- * call-seq:
270
- * RubyVM::ThreadFrame#dfp(n) -> object
271
- *
272
- * Returns a RubyVM object stored at dfp position <i>i</i>. The top object
273
- * is position 0.
274
- */
275
- static VALUE
276
- thread_frame_dfp(VALUE klass, VALUE index)
277
- {
278
- /* handled by THREAD_FRAME_FP_METHOD macro; */
279
- }
280
- #endif
281
- /* The above declaration is to make RDOC happy. */
282
- THREAD_FRAME_FP_METHOD(dfp)
283
-
284
- /*
285
- * call-seq:
286
- * RubyVM::ThreadFrame#lfp(i) -> object
287
- *
288
- * Returns a RubyVM object stored at lfp position <i>i</i>. The top object
289
- * is position 0. Negative values of <i>i</i> count from the end.
290
- */
291
- static VALUE
292
- thread_frame_lfp(VALUE klass, VALUE index)
293
- {
294
- if (!FIXNUM_P(index)) {
295
- rb_raise(rb_eTypeError, "integer argument expected");
296
- } else {
297
- long int i = FIX2INT(index);
298
- long int size;
299
-
300
- THREAD_FRAME_SETUP_WITH_ERROR ;
301
-
302
- size = tf->cfp->iseq->local_size;
303
- if (i < 0) i = size - i;
304
-
305
- if (i > size)
306
- rb_raise(rb_eIndexError,
307
- "local frame index %ld should be in the range %ld .. %ld",
308
- i, -size, size-1);
309
-
310
- return tf->cfp->lfp[-i]; /* stack grows "down" */
311
- }
312
- }
313
-
314
- #if 0
315
- /*
316
- * call-seq:
317
- * RubyVM::ThreadFrame#sp(n) -> object
318
- *
319
- * Returns a RubyVM object stored at stack position <i>i</i>. The top object
320
- * is position 0. 1 is the next object.
321
- */
322
- VALUE
323
- thread_frame_sp(VALUE klass, VALUE index)
324
- {
325
- /* handled by THREAD_FRAME_FP_METHOD macro; */
326
- }
327
- #endif
328
- /* The above declaration is to make RDOC happy.
329
- FIXME: Figure out a way to check if "index" is valid!
330
- */
331
- THREAD_FRAME_FP_METHOD(sp)
332
-
333
- static long int
334
- thread_frame_sp_size_internal(thread_frame_t *tf)
335
- {
336
- rb_control_frame_t *prev_cfp;
337
- long int ret_val;
338
- prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(tf->cfp);
339
- if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(tf->th, prev_cfp))
340
- return Qnil;
341
- ret_val = tf->cfp->sp - prev_cfp->sp - 1;
342
- /* FIXME: Why For C Functions we tack on 2 for this RubyVM::ENV? */
343
- if (RUBYVM_CFUNC_FRAME_P(tf->cfp)) ret_val += 2;
344
- return ret_val;
345
- }
346
-
347
- /*
348
- * call-seq:
349
- * RubyVM::ThreadFrame#sp_size -> FixNum
350
- *
351
- * Returns the number of stack or sp entries in the current
352
- * frame. That is the, number values that have been pushed onto the
353
- * stack since the current call. This is different than
354
- * RubyVM::ThreadFrame#stack_size which counts the number of frames in
355
- * the call stack. +nil+ is returned if there is an error.
356
- */
357
- VALUE
358
- thread_frame_sp_size(VALUE klass)
359
- {
360
- THREAD_FRAME_SETUP_WITH_ERROR ;
361
- return INT2FIX(thread_frame_sp_size_internal(tf));
362
- }
363
-
364
- /*
365
- * call-seq:
366
- * RubyVM::ThreadFrame#sp_set(n, newvalue) -> object
367
- *
368
- * Sets VM stack position <i>n</i> to <i>newvalue</i>. The top object
369
- * is position 0. 1 is the next object.
370
- */
371
- static VALUE
372
- thread_frame_sp_set(VALUE klass, VALUE index, VALUE newvalue)
373
- {
374
- if (!FIXNUM_P(index)) {
375
- rb_raise(rb_eTypeError, "integer argument expected");
376
- } else {
377
- long int i = FIX2INT(index);
378
- THREAD_FRAME_SETUP_WITH_ERROR ;
379
- if (i <= thread_frame_sp_size_internal(tf)) {
380
- /* stack grows "down" */
381
- tf->cfp->sp[-i] = newvalue;
382
- } else {
383
- rb_raise(rb_eArgError, "argument too big");
384
- }
385
- return newvalue;
386
- }
387
- }
388
-
389
- #ifndef NO_reg_pc
390
- /*
391
- * call-seq:
392
- * RubyVM::ThreadFrame#pc_offset=
393
- *
394
- * Sets pc to the offset given.
395
- * WARNING, this is pretty dangerous. You need to set this to a valid
396
- * instruction offset since little checking is done.
397
- */
398
- static VALUE
399
- thread_frame_set_pc_offset(VALUE klass, VALUE offset_val)
400
- {
401
- int offset;
402
- THREAD_FRAME_SETUP_WITH_ERROR ;
403
-
404
- if (!FIXNUM_P(offset_val)) {
405
- rb_raise(rb_eTypeError, "integer argument expected");
406
- } else {
407
- offset = FIX2INT(offset_val);
408
- if (RUBY_VM_NORMAL_ISEQ_P(tf->cfp->iseq) &&
409
- (tf->cfp->pc != 0 && tf->cfp->iseq != 0)) {
410
- tf->cfp->pc = tf->cfp->iseq->iseq_encoded + offset;
411
- }
412
- }
413
- return Qtrue;
414
- }
415
- #endif
416
-
417
- #if 0
418
- /*
419
- * call-seq:
420
- * RubyVM::ThreadFrame#flag -> Fixnum
421
- *
422
- * Returns the frame flags, a FIXNUM which should be interpreted as a
423
- * bitmask.
424
- *
425
- */
426
- static VALUE thread_frame_flag(VALUE klass)
427
- {
428
- /* handled by THREAD_FRAME_FIELD_METHOD macro; */
429
- }
430
- /* The above declaration is to make RDOC happy. */
431
- #endif
432
- THREAD_FRAME_FIELD_METHOD(flag) ;
433
-
434
- /*
435
- * call-seq:
436
- * RubyVM::ThreadFrame#argc -> Fixnum
437
- *
438
- * Returns the number of arguments that were actually passed
439
- * in the call to this frame. This differs from arity when
440
- * arity can take optional or "splat"ted parameters.
441
- *
442
- */
443
- static VALUE
444
- thread_frame_argc(VALUE klass)
445
- {
446
- THREAD_FRAME_SETUP_WITH_ERROR;
447
-
448
- if (RUBYVM_CFUNC_FRAME_P(tf->cfp)) {
449
- return INT2FIX(tf->cfp->me->def->body.cfunc.actual_argc);
450
- } else if (RUBY_VM_NORMAL_ISEQ_P(tf->cfp->iseq)) {
451
- return iseq_argc(thread_frame_iseq(klass));
452
- } else
453
- return Qnil;
454
- }
455
-
456
- /*
457
- * call-seq:
458
- * RubyVM::ThreadFrame#arity -> Fixnum
459
- *
460
- * Returns the number of arguments that would not be ignored.
461
- * See Ruby 1.9 proc_arity of proc.c
462
- *
463
- */
464
- static VALUE
465
- thread_frame_arity(VALUE klass)
466
- {
467
- THREAD_FRAME_SETUP_WITH_ERROR ;
468
-
469
- if (RUBY_VM_NORMAL_ISEQ_P(tf->cfp->iseq)) {
470
- return rb_iseq_arity(thread_frame_iseq(klass));
471
- } else if (RUBYVM_CFUNC_FRAME_P(tf->cfp)) {
472
- return INT2FIX(tf->cfp->me->def->body.cfunc.argc);
473
- } else
474
- return Qnil;
475
- }
476
-
477
- /*
478
- * call-seq:
479
- * RubyVM::ThreadFrame#binding -> binding
480
- *
481
- * Returns a binding for a given thread frame.
482
- */
483
- static VALUE
484
- thread_frame_binding(VALUE klass)
485
- {
486
- THREAD_FRAME_SETUP_WITH_ERROR ;
487
-
488
- {
489
- rb_binding_t *bind = 0;
490
- VALUE bindval = rb_binding_frame_new(tf->th, tf->cfp);
491
- GetBindingPtr(bindval, bind);
492
- bind->line_no = rb_vm_get_sourceline(tf->cfp);
493
- if (tf->cfp->iseq) {
494
- bind->filename = tf->cfp->iseq->filename;
495
- } else {
496
- bind->filename = tf->th->vm->progname;
497
- }
498
- return bindval;
499
- }
500
- /* NOTREACHED */
501
- return Qnil;
502
- }
503
-
504
- /*
505
- * call-seq:
506
- * RubyVM::ThreadFrame#equal(tf) -> bool
507
- *
508
- * Returns true if two thread frames are equal.
509
- */
510
- static VALUE
511
- thread_frame_equal(VALUE klass, VALUE tfval2)
512
- {
513
- THREAD_FRAME_SETUP_WITH_ERROR ;
514
-
515
- {
516
- thread_frame_t *tf2;
517
- if (!rb_obj_is_kind_of(tfval2, rb_cThreadFrame)) {
518
- rb_raise(rb_eTypeError,
519
- "comparison argument must be an instance of %s (is %s)",
520
- rb_obj_classname(klass), rb_obj_classname(tfval2));
521
- }
522
- Data_Get_Struct(tfval2, thread_frame_t, tf2);
523
- if (Qtrue == thread_frame_invalid_internal(tf2))
524
- rb_raise(rb_eThreadFrameError, "invalid frame");
525
-
526
- /* And just when you thought I'd never get around to the
527
- actual comparison...
528
-
529
- Comparing cfp's should be enough, but we'll throw in the thread
530
- for good measure.
531
- */
532
- return (tf->th == tf2->th && tf->cfp == tf2->cfp)
533
- ? Qtrue : Qfalse;
534
- }
535
- /* NOTREACHED */
536
- return Qnil;
537
- }
538
-
539
- /*
540
- * call-seq:
541
- * RubyVM::ThreadFrame.new(thread) -> thread_frame_object
542
- *
543
- * Returns an RubyVM::ThreadFrame object which can contains dynamic frame
544
- * information. Don't use this directly. Instead use one of the
545
- * class methods.
546
- *
547
- * RubyVM::ThreadFrame::VERSION => 0.1
548
- * RubyVM::ThreadFrame::current.flag => 72
549
- * RubyVM::ThreadFrame::current.proc => false
550
- * RubyVM::ThreadFrame::current.self => 'main'
551
- */
552
- static VALUE
553
- thread_frame_initialize(VALUE tfval, VALUE thval)
554
- {
555
- thread_frame_t *tf = thread_frame_t_alloc(tfval);
556
- GET_THREAD_PTR ;
557
- memset(tf, 0, sizeof(thread_frame_t));
558
- DATA_PTR(tfval) = tf;
559
- SAVE_FRAME(tf, th) ;
560
- return tfval;
561
- }
562
-
563
- /*
564
- * call-seq:
565
- * RubyVM::ThreadFrame#invalid? -> Boolean
566
- *
567
- * Returns true if the frame is no longer valid. On the other hand,
568
- * since the test we use is weak, returning false might not mean the
569
- * frame is valid, just that we can't disprove that it is not invalid.
570
- *
571
- * It is suggested that frames are used in a way that ensures they will
572
- * be valid. In particular frames should have local scope and frames to
573
- * threads other than the running one should be stopped while the frame
574
- * variable is active.
575
- */
576
- static VALUE
577
- thread_frame_invalid(VALUE klass)
578
- {
579
- THREAD_FRAME_SETUP ;
580
- return thread_frame_invalid_internal(tf);
581
- }
582
-
583
- static VALUE
584
- thread_frame_is_return_stop(VALUE klass)
585
- {
586
- THREAD_FRAME_SETUP ;
587
- return (tf->cfp->tracing & VM_FRAME_TRACE_RETURN) ? Qtrue : Qfalse;
588
- }
589
-
590
- static VALUE
591
- thread_frame_is_trace_off(VALUE klass)
592
- {
593
- THREAD_FRAME_SETUP ;
594
- return (tf->cfp->tracing & VM_FRAME_TRACE_OFF) ? Qtrue : Qfalse;
595
- }
596
-
597
- /*
598
- * call-seq:
599
- * ThreadFrame#method -> String or nil
600
- *
601
- * Returns the method associated with the frame or nil of none.
602
- * ThreadFrameError can be raised if the threadframe
603
- * object is no longer valid.
604
- */
605
- static VALUE
606
- thread_frame_method(VALUE klass)
607
- {
608
- THREAD_FRAME_SETUP_WITH_ERROR ; \
609
-
610
- switch (VM_FRAME_TYPE(tf->cfp)) {
611
- case VM_FRAME_MAGIC_BLOCK:
612
- case VM_FRAME_MAGIC_EVAL:
613
- case VM_FRAME_MAGIC_LAMBDA:
614
- case VM_FRAME_MAGIC_METHOD:
615
- case VM_FRAME_MAGIC_TOP:
616
- if (RUBY_VM_NORMAL_ISEQ_P(tf->cfp->iseq))
617
- return tf->cfp->iseq->name;
618
- else
619
- return Qnil; /* unknown */
620
- case VM_FRAME_MAGIC_CFUNC: {
621
- const char *method_name = rb_id2name(tf->cfp->me->def->original_id);
622
- return rb_str_new2((NULL == method_name) ? "" : method_name );
623
- }
624
- default:
625
- /* FIXME */
626
- return thread_frame_type(klass);
627
- }
628
- /* NOTREACHED */
629
- return Qnil;
630
- }
631
-
632
- /*
633
- * call-seq:
634
- * ThreadFrame#pc_offset -> Fixnum
635
- *
636
- * Returns the offset inside the iseq or "program-counter offset" or -1
637
- * If invalid/unstarted. ThreadFrameError can be raised if the threadframe
638
- * object is no longer valid.
639
- */
640
- static VALUE
641
- thread_frame_pc_offset(VALUE klass)
642
- {
643
- unsigned long pc;
644
- THREAD_FRAME_SETUP_WITH_ERROR ;
645
-
646
- if (RUBY_VM_NORMAL_ISEQ_P(tf->cfp->iseq) &&
647
- (tf->cfp->pc != 0 && tf->cfp->iseq != 0)) {
648
- pc = tf->cfp->pc - tf->cfp->iseq->iseq_encoded;
649
- return INT2FIX(pc);
650
- } else {
651
- return INT2FIX(-1);
652
- }
653
- }
654
-
655
-
656
- /*
657
- * call-seq:
658
- * ThreadFrame#iseq -> ISeq
659
- *
660
- * Returns an instruction sequence object from the instruction sequence
661
- * found inside the ThreadFrame object or nil if there is none.
662
- *
663
- */
664
- static VALUE
665
- thread_frame_iseq(VALUE klass)
666
- {
667
- rb_iseq_t *iseq;
668
- VALUE rb_iseq;
669
- THREAD_FRAME_SETUP_WITH_ERROR ;
670
- iseq = tf->cfp->iseq;
671
- if (!iseq) return Qnil;
672
- rb_iseq = iseq_alloc_shared(rb_cISeq);
673
- RDATA(rb_iseq)->data = iseq;
674
- return rb_iseq;
675
- }
676
-
677
- /*
678
- See the above thread_frame_prev comment for what's going on here.
679
- */
680
- static VALUE
681
- thread_frame_next(VALUE klass)
682
- {
683
- rb_control_frame_t *cfp = NULL;
684
- THREAD_FRAME_SETUP_WITH_ERROR ;
685
- cfp = RUBY_VM_NEXT_CONTROL_FRAME(tf->cfp);
686
-
687
- if ((void *)(cfp) <= (void *)(tf->th->stack))
688
- return Qnil;
689
- else {
690
- thread_frame_t *next_tf;
691
- VALUE next = thread_frame_alloc(rb_cThreadFrame);
692
- thread_frame_t_alloc(next);
693
- Data_Get_Struct(next, thread_frame_t, next_tf);
694
- next_tf->th = tf->th;
695
- next_tf->cfp = cfp;
696
- COPY_SIGNATURE(tf, cfp);
697
- return next;
698
- }
699
- }
700
-
701
- /*
702
- * call-seq:
703
- * RubyVM::ThreadFrame#prev(n=1) -> thread_frame_object
704
- *
705
- * Returns a RubyVM::ThreadFrame object for the frame prior to the
706
- * ThreadFrame object or +nil+ if there is none. Setting n=0 just
707
- * returns the object passed. A negative starts from the end. So
708
- * prev(-1) is the top frame. Counts outside of the range
709
- * -stack_size .. stack_size-1 exceed the the range of the stack and
710
- * return nil.
711
- *
712
- */
713
- VALUE
714
- thread_frame_prev(int argc, VALUE *argv, VALUE klass)
715
- {
716
- VALUE nv;
717
- int n;
718
-
719
- THREAD_FRAME_SETUP_WITH_ERROR ;
720
-
721
- rb_scan_args(argc, argv, "01", &nv);
722
-
723
- if (Qnil == nv)
724
- n = 1;
725
- else if (!FIXNUM_P(nv)) {
726
- rb_raise(rb_eTypeError, "integer argument expected");
727
- } else
728
- n = FIX2INT(nv);
729
-
730
- if (n < 0) {
731
- int stack_size = thread_frame_stack_size_internal(tf->cfp, tf->th);
732
- if (-n > stack_size) return Qnil;
733
- n = stack_size + n;
734
- }
735
- if (n == 0) return klass;
736
- return thread_frame_prev_internal(tf->cfp, tf->th, n);
737
- }
738
-
739
- /*
740
- See the above thread_frame_prev comment for what's going on here.
741
- */
742
- static VALUE
743
- thread_frame_prev_internal(rb_control_frame_t *prev_cfp, rb_thread_t *th,
744
- int n)
745
- {
746
- thread_frame_t *tf;
747
- VALUE prev;
748
- rb_control_frame_t *cfp = NULL;
749
-
750
- for (; n > 0; n--) {
751
- cfp = prev_cfp;
752
- prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
753
- if (VM_FRAME_TYPE(prev_cfp) == VM_FRAME_MAGIC_FINISH) {
754
- prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(prev_cfp);
755
- }
756
- if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, prev_cfp))
757
- return Qnil;
758
- }
759
- if (!cfp) return Qnil;
760
-
761
- prev = thread_frame_alloc(rb_cThreadFrame);
762
- thread_frame_t_alloc(prev);
763
- Data_Get_Struct(prev, thread_frame_t, tf);
764
- tf->th = th;
765
- tf->cfp = prev_cfp;
766
- COPY_SIGNATURE(tf, tf->cfp);
767
- return prev;
768
- }
769
-
770
- THREAD_FRAME_FIELD_METHOD(proc) ;
771
- THREAD_FRAME_FIELD_METHOD(self) ;
772
-
773
- static VALUE
774
- thread_frame_return_stop_set(VALUE klass, VALUE boolval)
775
- {
776
- short int boolmask = !(NIL_P(boolval) || Qfalse == boolval);
777
- THREAD_FRAME_SETUP ;
778
-
779
- if (boolmask)
780
- tf->cfp->tracing |= VM_FRAME_TRACE_RETURN;
781
- else
782
- tf->cfp->tracing &= ~VM_FRAME_TRACE_RETURN;
783
- return boolval;
784
- }
785
-
786
- static VALUE
787
- thread_frame_trace_off_set(VALUE klass, VALUE boolval)
788
- {
789
- short int boolmask = !(NIL_P(boolval) || Qfalse == boolval);
790
- THREAD_FRAME_SETUP ;
791
-
792
- if (boolmask)
793
- tf->cfp->tracing |= VM_FRAME_TRACE_OFF;
794
- else
795
- tf->cfp->tracing &= ~VM_FRAME_TRACE_OFF;
796
- return boolval;
797
- }
798
-
799
- /*
800
- * call-seq:
801
- * RubyVM::ThreadFrame::current -> thread_frame_object
802
- *
803
- * Returns a ThreadFrame object for the currently executing thread.
804
- * Same as: RubyVM::ThreadFrame.new(Thread::current)
805
- */
806
- static VALUE
807
- thread_frame_s_current(VALUE klass)
808
- {
809
- thread_frame_t *tf = thread_frame_t_alloc(klass);
810
- SAVE_FRAME(tf, ruby_current_thread) ;
811
- return Data_Wrap_Struct(klass, thread_frame_mark, tf_free, tf);
812
- }
813
-
814
- /*
815
- * call-seq:
816
- * RubyVM::ThreadFrame::prev(thread) -> threadframe_object
817
- * RubyVM::ThreadFrame::prev(thread, n) -> threadframe_object
818
- * RubyVM::ThreadFrame::prev -> threadframe_object
819
- * RubyVM::ThreadFrame::prev(n) -> threadframe_object
820
- *
821
- * In the first form, we return a RubyVM::ThreadFrame prior to the
822
- * Thread object passed. That is we go back one frame from the
823
- * current frfame.
824
- *
825
- * In the second form we try to go back that many thread frames.
826
- *
827
- * In the the third form, the current thread is assumed, and like the
828
- * first form we go back one frame.
829
- *
830
- * The fourth form, like the third form, we assume the current
831
- * thread. And like the first form we go back we try to back a
832
- * FixNum number of entries.
833
- *
834
- * When count +n+ is given 1 is synonymous with the previous frame
835
- * and 0 is invalid. If the +n+ is negative, we count from the bottom
836
- * of the frame stack.
837
- *
838
- * In all cases we return a RubyVM::ThreadFrame or nil if we can't
839
- * go back (or forward for a negative +n+) that many frames.
840
- *
841
- */
842
- static VALUE
843
- thread_frame_s_prev(int argc, VALUE *argv, VALUE klass)
844
- {
845
- VALUE first_val;
846
- VALUE second_val;
847
- VALUE thval = Qnil;
848
- int prev_count = 0;
849
- rb_thread_t *th = NULL;
850
-
851
- /* Such complicated options processing. But we do want this
852
- routine to be convenient. */
853
- rb_scan_args(argc, argv, "02", &first_val, &second_val);
854
- switch (argc) {
855
- case 0:
856
- th = ruby_current_thread;
857
- /* Do'nt count the RubyVM::ThreadFrame.prev call */
858
- prev_count = 2;
859
- break;
860
- case 1:
861
- if (FIXNUM_P(first_val)) {
862
- prev_count = FIX2INT(first_val);
863
- if (prev_count > 0) prev_count++ ;
864
- th = ruby_current_thread;
865
- } else
866
- if (Qtrue == rb_obj_is_kind_of(first_val, rb_cThread)) {
867
- GetThreadPtr(first_val, th);
868
- /* Don't count the RubyVM::ThreadFrame.prev call */
869
- prev_count = 1;
870
- } else {
871
- rb_raise(rb_eTypeError,
872
- "FixNum or ThreadFrame object expected for first argument");
873
- }
874
- break;
875
- case 2:
876
- if (Qtrue == rb_obj_is_kind_of(first_val, rb_cThread)) {
877
- GetThreadPtr(first_val, th);
878
- } else {
879
- rb_raise(rb_eTypeError,
880
- "ThreadFrame object expected for first argument");
881
- }
882
- if (FIXNUM_P(second_val)) {
883
- prev_count = FIX2INT(second_val);
884
- } else
885
- rb_raise(rb_eTypeError,
886
- "FixNum previous count expected for second argument");
887
- break;
888
- default:
889
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..2)", argc);
890
- }
891
-
892
- if (0 == prev_count) {
893
- rb_raise(rb_eArgError,
894
- "previous count can not be 0. Use current instead of prev");
895
- }
896
-
897
- if (0 > prev_count) {
898
- int stack_size = thread_frame_stack_size_internal(th->cfp, th);
899
- if (-prev_count > stack_size) return Qnil;
900
- prev_count = stack_size + prev_count;
901
- }
902
-
903
- return thread_frame_prev_internal(th->cfp, th, prev_count);
904
- }
905
-
906
- /*
907
- * call-seq:
908
- * RubyVM::ThreadFrame#source_container() -> [Type, String]
909
- *
910
- * Returns a tuple representing kind of container, e.g. file
911
- * eval'd string object, and the name of the container. If file,
912
- * it would be a file name. If an eval'd string it might be the string.
913
- */
914
- static VALUE
915
- thread_frame_source_container(VALUE klass)
916
- {
917
- VALUE filename = Qnil;
918
- const char *contain_type;
919
- rb_control_frame_t *cfp;
920
- int is_eval = 0;
921
-
922
- THREAD_FRAME_SETUP ;
923
-
924
- for ( cfp = tf->cfp; cfp && !cfp->iseq && RUBYVM_CFUNC_FRAME_P(cfp);
925
- cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp) ) ;
926
-
927
-
928
- if (cfp->iseq)
929
- filename = cfp->iseq->filename;
930
- else {
931
- if (tf->th->vm->progname)
932
- filename = tf->th->vm->progname;
933
- else
934
- return Qnil;
935
- }
936
-
937
- contain_type = source_container_type(filename);
938
-
939
- is_eval = ( 0 == strcmp("string", contain_type)
940
- && VM_FRAME_MAGIC_EVAL == VM_FRAME_TYPE(tf->cfp) );
941
-
942
- if ( is_eval ) {
943
- /* Try to pick up string from stack. */
944
- VALUE prev = thread_frame_prev_internal(tf->cfp, tf->th, 1);
945
- thread_frame_t *prev_tf;
946
- Data_Get_Struct(prev, thread_frame_t, prev_tf);
947
-
948
- if (RUBYVM_CFUNC_FRAME_P(prev_tf->cfp) &&
949
- thread_frame_stack_size_internal(prev_tf->cfp, prev_tf->th) >= 3)
950
- filename = thread_frame_sp(prev, INT2FIX(3));
951
- }
952
-
953
- return rb_ary_new3(2, rb_str_new2(contain_type), filename);
954
- }
955
-
956
- /*
957
- * call-seq:
958
- * RubyVM::ThreadFrame#source_location() -> Array
959
- *
960
- * Returns an array of source location positions that match
961
- * +tf.instruction_offset+. A source location position is left
962
- * implementation dependent. It could be line number, a line number
963
- * and start and end column, or a start line number, start column, end
964
- * line number, end column.
965
- */
966
- static VALUE
967
- thread_frame_source_location(VALUE klass)
968
- {
969
- rb_control_frame_t *cfp;
970
- THREAD_FRAME_SETUP ;
971
-
972
- /* For now, it appears like we have line numbers only when there
973
- is an instruction sequence. The heuristic that is used by
974
- vm_backtrace_each of vm.c seems to be to use the line number of
975
- the closest control frame that has an instruction sequence.
976
- FIXME: investigate whether this is always the most accurate location. If
977
- not, improve.
978
- */
979
- for ( cfp = tf->cfp; cfp && !cfp->iseq && RUBYVM_CFUNC_FRAME_P(cfp);
980
- cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp) ) ;
981
-
982
- return (cfp->iseq)
983
- /* NOTE: for now sourceline returns a single int. In the
984
- future it might return an array of ints.
985
- */
986
- ? rb_ary_new3(1, INT2FIX(rb_vm_get_sourceline(cfp)))
987
- : Qnil;
988
- }
989
-
990
- /*
991
- * call-seq:
992
- * RubyVM::ThreadFrame#stack_size -> Fixnum;
993
- *
994
- * Returns a count of the number of frames including the current one.
995
- * ThreadFrame#prev(ThreadFrame#stack_size) = nil
996
- * ThreadFrame#prev(ThreadFrame#stack_size-1) = top frame
997
- *
998
- *
999
- */
1000
- static VALUE
1001
- thread_frame_stack_size(VALUE klass)
1002
- {
1003
- THREAD_FRAME_SETUP ;
1004
- return INT2FIX(thread_frame_stack_size_internal(tf->cfp, tf->th));
1005
- }
1006
-
1007
- /*
1008
- See the above thread_frame_stack_size comment for what's going on here.
1009
- */
1010
- static int
1011
- thread_frame_stack_size_internal(rb_control_frame_t *cfp, rb_thread_t *th)
1012
- {
1013
- int n;
1014
- for ( n = 0;
1015
- !RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp);
1016
- cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)) {
1017
- n++;
1018
- if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_FINISH) {
1019
- cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
1020
- if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp))
1021
- break;
1022
- }
1023
- }
1024
- return n;
1025
- }
1026
-
1027
- /*
1028
- * call-seq:
1029
- * RubyVM::ThreadFrame#thread -> thread
1030
- *
1031
- * Returns the thread object for the thread frame.
1032
- */
1033
- static VALUE
1034
- thread_frame_thread(VALUE klass)
1035
- {
1036
- THREAD_FRAME_SETUP ;
1037
- return tf->th->self;
1038
- }
1039
-
1040
- /* Extracted from vm_dump.c. Would be nice to have this routine put there
1041
- and used in both places. */
1042
- static const char *
1043
- frame_magic2str(rb_control_frame_t *cfp)
1044
- {
1045
- switch (VM_FRAME_TYPE(cfp)) {
1046
- case VM_FRAME_MAGIC_TOP:
1047
- return "TOP";
1048
- case VM_FRAME_MAGIC_METHOD:
1049
- return "METHOD";
1050
- case VM_FRAME_MAGIC_CLASS:
1051
- return "CLASS";
1052
- case VM_FRAME_MAGIC_BLOCK:
1053
- return "BLOCK";
1054
- case VM_FRAME_MAGIC_FINISH:
1055
- return "FINISH";
1056
- case VM_FRAME_MAGIC_CFUNC:
1057
- return "CFUNC";
1058
- case VM_FRAME_MAGIC_PROC:
1059
- return "PROC";
1060
- case VM_FRAME_MAGIC_LAMBDA:
1061
- return "LAMBDA";
1062
- case VM_FRAME_MAGIC_IFUNC:
1063
- return "IFUNC";
1064
- case VM_FRAME_MAGIC_EVAL:
1065
- return "EVAL";
1066
- case 0:
1067
- return "------";
1068
- default:
1069
- return "(none)";
1070
- }
1071
- /* NOTREACHED */
1072
- return "?";
1073
- }
1074
-
1075
- /*
1076
- * call-seq:
1077
- * ThreadFrame#type -> String
1078
- *
1079
- * Returns the kind of frame. Basically interprets VM_FRAME_MAGIC for
1080
- * tf->cfp->flag
1081
- */
1082
- static VALUE
1083
- thread_frame_type(VALUE klass)
1084
- {
1085
- THREAD_FRAME_SETUP ;
1086
- return rb_str_new2(frame_magic2str(tf->cfp));
1087
- }
1088
-
1089
- void
1090
- Init_thread_frame(void)
1091
- {
1092
- /* Additions to RubyVM */
1093
- rb_cThreadFrame = rb_define_class_under(rb_cRubyVM, "ThreadFrame",
1094
- rb_cObject);
1095
- rb_define_method(rb_cThread, "threadframe", thread_frame_threadframe, 0);
1096
-
1097
- /* Thread::Frame */
1098
- rb_define_const(rb_cThreadFrame, "VERSION",
1099
- rb_str_new2(THREADFRAME_VERSION));
1100
- rb_define_alloc_func(rb_cThreadFrame, thread_frame_alloc);
1101
-
1102
- rb_define_method(rb_cThreadFrame, "invalid?", thread_frame_invalid, 0);
1103
-
1104
- /* RubyVM::ThreadFrame */
1105
- rb_define_method(rb_cThreadFrame, "argc", thread_frame_argc, 0);
1106
- rb_define_method(rb_cThreadFrame, "arity", thread_frame_arity, 0);
1107
- rb_define_method(rb_cThreadFrame, "binding", thread_frame_binding, 0);
1108
- rb_define_method(rb_cThreadFrame, "dfp", thread_frame_dfp, 1);
1109
- rb_define_method(rb_cThreadFrame, "flag", thread_frame_flag, 0);
1110
- rb_define_method(rb_cThreadFrame, "initialize", thread_frame_initialize, 1);
1111
- rb_define_method(rb_cThreadFrame, "iseq", thread_frame_iseq, 0);
1112
- rb_define_method(rb_cThreadFrame, "lfp", thread_frame_lfp, 1);
1113
- rb_define_method(rb_cThreadFrame, "method", thread_frame_method, 0);
1114
- rb_define_method(rb_cThreadFrame, "next", thread_frame_next, 0);
1115
- rb_define_method(rb_cThreadFrame, "pc_offset", thread_frame_pc_offset, 0);
1116
- rb_define_method(rb_cThreadFrame, "prev", thread_frame_prev, -1);
1117
- rb_define_method(rb_cThreadFrame, "proc", thread_frame_proc, 0);
1118
- rb_define_method(rb_cThreadFrame, "return_stop=", thread_frame_return_stop_set, 1);
1119
- rb_define_method(rb_cThreadFrame, "return_stop?", thread_frame_is_return_stop, 0);
1120
- rb_define_method(rb_cThreadFrame, "self", thread_frame_self, 0);
1121
- rb_define_method(rb_cThreadFrame, "source_container",
1122
- thread_frame_source_container, 0);
1123
- rb_define_method(rb_cThreadFrame, "source_location",
1124
- thread_frame_source_location, 0);
1125
-
1126
- /* sp[] and sp[]= would be neater, but that would require making sp an
1127
- object which I am not sure I want to do.
1128
- */
1129
- rb_define_method(rb_cThreadFrame, "sp", thread_frame_sp, 1);
1130
- rb_define_method(rb_cThreadFrame, "sp_set", thread_frame_sp_set, 2);
1131
- rb_define_method(rb_cThreadFrame, "sp_size", thread_frame_sp_size, 0);
1132
-
1133
- /* I think I like the more explicit stack_size over size or length. */
1134
- rb_define_method(rb_cThreadFrame, "stack_size",
1135
- thread_frame_stack_size, 0);
1136
-
1137
- rb_define_method(rb_cThreadFrame, "thread", thread_frame_thread, 0);
1138
- rb_define_method(rb_cThreadFrame, "trace_off?", thread_frame_is_trace_off, 0);
1139
- rb_define_method(rb_cThreadFrame, "trace_off=", thread_frame_trace_off_set, 1);
1140
- rb_define_method(rb_cThreadFrame, "type", thread_frame_type, 0);
1141
-
1142
- rb_define_method(rb_cThreadFrame, "equal?",
1143
- thread_frame_equal, 1);
1144
-
1145
- #ifndef NO_reg_pc
1146
- rb_define_method(rb_cThreadFrame, "pc_offset=",
1147
- thread_frame_set_pc_offset, 1);
1148
- #endif
1149
-
1150
-
1151
- rb_eThreadFrameError = rb_define_class("ThreadFrameError",
1152
- rb_eStandardError);
1153
-
1154
- rb_define_singleton_method(rb_cThreadFrame, "prev",
1155
- thread_frame_s_prev, -1);
1156
- rb_define_singleton_method(rb_cThreadFrame, "current",
1157
- thread_frame_s_current, 0);
1158
-
1159
-
1160
- /* Perform the other C extension initializations. */
1161
- Init_iseq_extra();
1162
- Init_proc_extra();
1163
- Init_thread_extra();
1164
- Init_thread_extra();
1165
- }