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