Class: RubyVM::ThreadFrame
- Inherits:
-
Object
- Object
- RubyVM::ThreadFrame
- Defined in:
- ext/thread_frame.c
Constant Summary
- VERSION =
Frame
rb_str_new2(THREADFRAME_VERSION)
Class Method Summary (collapse)
-
+ (Object) RubyVM::ThreadFrame::current
Returns a ThreadFrame object for the currently executing thread.
-
+ (Object) prev
In the first form, we return a RubyVM::ThreadFrame prior to the Thread object passed.
Instance Method Summary (collapse)
-
- (Fixnum) RubyVM::ThreadFrame
Returns the number of arguments that were actually passed in the call to this frame.
-
- (Fixnum) RubyVM::ThreadFrame
Returns the number of arguments that would not be ignored.
-
- (Binding) RubyVM::ThreadFrame
Returns a binding for a given thread frame.
-
- (Object) RubyVM::ThreadFrame
Returns a RubyVM object stored at dfp position i.
-
- (Boolean) RubyVM::ThreadFrame
Returns true if two thread frames are equal.
-
- (Fixnum) RubyVM::ThreadFrame
Returns the frame flags, a FIXNUM which should be interpreted as a bitmask.
-
- (Object) RubyVM::ThreadFrame.new(thread)
constructor
Returns an RubyVM::ThreadFrame object which can contains dynamic frame information.
-
- (Boolean) RubyVM::ThreadFrame
Returns true if the frame is no longer valid.
-
- (ISeq) iseq
Returns an instruction sequence object from the instruction sequence found inside the ThreadFrame object or nil if there is none.
-
- (Object) RubyVM::ThreadFrame
Returns a RubyVM object stored at lfp position i.
-
- (String?) method
Returns the method associated with the frame or nil of none.
-
- (Object) next
See the above thread_frame_prev comment for what's going on here.
-
- (Fixnum) pc_offset
Returns the offset inside the iseq or "program-counter offset" or -1 If invalid/unstarted.
-
- (Object) RubyVM::ThreadFrame
Sets pc to the offset given.
-
- (Object) RubyVM::ThreadFrame
Returns a RubyVM::ThreadFrame object for the frame prior to the ThreadFrame object or nil if there is none.
- - (Object) proc
- - (Object) return_stop=
- - (Boolean) return_stop?
- - (Object) self
-
- (Array, String) RubyVM::ThreadFrame
Returns a tuple representing kind of container, e.g.
-
- (Array) RubyVM::ThreadFrame
Returns an array of source location positions that match tf.instruction_offset.
-
- (Object) RubyVM::ThreadFrame
Returns a RubyVM object stored at stack position i.
-
- (Object) RubyVM::ThreadFrame
Sets VM stack position n to newvalue.
-
- (FixNum) RubyVM::ThreadFrame
Returns the number of stack or sp entries in the current frame.
-
- (Fixnum;) RubyVM::ThreadFrame
Returns a count of the number of frames including the current one.
-
- (Object) RubyVM::ThreadFrame
Returns the thread object for the thread frame.
- - (Object) trace_off=
- - (Boolean) trace_off?
-
- (String) type
Returns the kind of frame.
Constructor Details
- (Object) RubyVM::ThreadFrame.new(thread)
Returns an RubyVM::ThreadFrame object which can contains dynamic frame information. Don't use this directly. Instead use one of the class methods.
RubyVM::ThreadFrame::VERSION => 0.1
RubyVM::ThreadFrame::current.flag => 72
RubyVM::ThreadFrame::current.proc => false
RubyVM::ThreadFrame::current.self => 'main'
|
|
# File 'ext/thread_frame.c'
static VALUE
thread_frame_initialize(VALUE tfval, VALUE thval)
{
thread_frame_t *tf = thread_frame_t_alloc(tfval);
GET_THREAD_PTR ;
memset(tf, 0, sizeof(thread_frame_t));
DATA_PTR(tfval) = tf;
SAVE_FRAME(tf, th) ;
return tfval;
}
|
Class Method Details
+ (Object) RubyVM::ThreadFrame::current
Returns a ThreadFrame object for the currently executing thread. Same as: RubyVM::ThreadFrame.new(Thread::current)
|
|
# File 'ext/thread_frame.c'
static VALUE
thread_frame_s_current(VALUE klass)
{
thread_frame_t *tf = thread_frame_t_alloc(klass);
SAVE_FRAME(tf, ruby_current_thread) ;
return Data_Wrap_Struct(klass, thread_frame_mark, tf_free, tf);
}
|
+ (Object) RubyVM::ThreadFrame::prev(thread) + (Object) RubyVM::ThreadFrame::prev(thread, n) + (Object) RubyVM::ThreadFrame::prev + (Object) RubyVM::ThreadFrame::prev(n)
In the first form, we return a RubyVM::ThreadFrame prior to the Thread object passed. That is we go back one frame from the current frfame.
In the second form we try to go back that many thread frames.
In the the third form, the current thread is assumed, and like the first form we go back one frame.
The fourth form, like the third form, we assume the current thread. And like the first form we go back we try to back a FixNum number of entries.
When count n is given 1 is synonymous with the previous frame and 0 is invalid. If the n is negative, we count from the bottom of the frame stack.
In all cases we return a RubyVM::ThreadFrame or nil if we can't go back (or forward for a negative n) that many frames.
|
|
# File 'ext/thread_frame.c'
static VALUE
thread_frame_s_prev(int argc, VALUE *argv, VALUE klass)
{
VALUE first_val;
VALUE second_val;
VALUE thval = Qnil;
int prev_count = 0;
rb_thread_t *th = NULL;
/* Such complicated options processing. But we do want this
routine to be convenient. */
rb_scan_args(argc, argv, "02", &first_val, &second_val);
switch (argc) {
case 0:
th = ruby_current_thread;
/* Do'nt count the RubyVM::ThreadFrame.prev call */
prev_count = 2;
break;
case 1:
if (FIXNUM_P(first_val)) {
prev_count = FIX2INT(first_val);
if (prev_count > 0) prev_count++ ;
th = ruby_current_thread;
}
|
Instance Method Details
- (Fixnum) RubyVM::ThreadFrame
Returns the number of arguments that were actually passed in the call to this frame. This differs from arity when arity can take optional or "splat"ted parameters.
|
|
# File 'ext/thread_frame.c'
static VALUE
thread_frame_argc(VALUE klass)
{
THREAD_FRAME_SETUP_WITH_ERROR;
if (RUBYVM_CFUNC_FRAME_P(tf->cfp)) {
return INT2FIX(tf->cfp->me->def->body.cfunc.actual_argc);
}
|
- (Fixnum) RubyVM::ThreadFrame
Returns the number of arguments that would not be ignored. See Ruby 1.9 proc_arity of proc.c
|
|
# File 'ext/thread_frame.c'
static VALUE
thread_frame_arity(VALUE klass)
{
THREAD_FRAME_SETUP_WITH_ERROR ;
if (RUBY_VM_NORMAL_ISEQ_P(tf->cfp->iseq)) {
return rb_iseq_arity(thread_frame_iseq(klass));
}
|
- (Binding) RubyVM::ThreadFrame
Returns a binding for a given thread frame.
|
|
# File 'ext/thread_frame.c'
static VALUE
thread_frame_binding(VALUE klass)
{
THREAD_FRAME_SETUP_WITH_ERROR ;
{
rb_binding_t *bind = 0;
VALUE bindval = rb_binding_frame_new(tf->th, tf->cfp);
GetBindingPtr(bindval, bind);
bind->line_no = rb_vm_get_sourceline(tf->cfp);
if (tf->cfp->iseq) {
bind->filename = tf->cfp->iseq->filename;
}
|
- (Object) RubyVM::ThreadFrame
Returns a RubyVM object stored at dfp position i. The top object is position 0.
|
|
# File 'ext/thread_frame.c'
static VALUE
thread_frame_dfp(VALUE klass, VALUE index)
{
/* handled by THREAD_FRAME_FP_METHOD macro; */
}
|
- (Boolean) RubyVM::ThreadFrame
Returns true if two thread frames are equal.
|
|
# File 'ext/thread_frame.c'
static VALUE
thread_frame_equal(VALUE klass, VALUE tfval2)
{
THREAD_FRAME_SETUP_WITH_ERROR ;
{
thread_frame_t *tf2;
if (!rb_obj_is_kind_of(tfval2, rb_cThreadFrame)) {
rb_raise(rb_eTypeError,
"comparison argument must be an instance of %s (is %s)",
rb_obj_classname(klass), rb_obj_classname(tfval2));
}
|
- (Fixnum) RubyVM::ThreadFrame
Returns the frame flags, a FIXNUM which should be interpreted as a bitmask.
|
|
# File 'ext/thread_frame.c'
static VALUE thread_frame_flag(VALUE klass)
{
/* handled by THREAD_FRAME_FIELD_METHOD macro; */
}
|
- (Boolean) RubyVM::ThreadFrame
Returns true if the frame is no longer valid. On the other hand, since the test we use is weak, returning false might not mean the frame is valid, just that we can't disprove that it is not invalid.
It is suggested that frames are used in a way that ensures they will be valid. In particular frames should have local scope and frames to threads other than the running one should be stopped while the frame variable is active.
|
|
# File 'ext/thread_frame.c'
static VALUE
thread_frame_invalid(VALUE klass)
{
THREAD_FRAME_SETUP ;
return thread_frame_invalid_internal(tf);
}
|
- (ISeq) iseq
Returns an instruction sequence object from the instruction sequence found inside the ThreadFrame object or nil if there is none.
|
|
# File 'ext/thread_frame.c'
static VALUE
thread_frame_iseq(VALUE klass)
{
rb_iseq_t *iseq;
VALUE rb_iseq;
THREAD_FRAME_SETUP_WITH_ERROR ;
iseq = tf->cfp->iseq;
if (!iseq) return Qnil;
rb_iseq = iseq_alloc_shared(rb_cISeq);
RDATA(rb_iseq)->data = iseq;
return rb_iseq;
}
|
- (Object) RubyVM::ThreadFrame
Returns a RubyVM object stored at lfp position i. The top object is position 0. Negative values of i count from the end.
|
|
# File 'ext/thread_frame.c'
static VALUE
thread_frame_lfp(VALUE klass, VALUE index)
{
if (!FIXNUM_P(index)) {
rb_raise(rb_eTypeError, "integer argument expected");
}
|
- (String?) method
Returns the method associated with the frame or nil of none. ThreadFrameError can be raised if the threadframe object is no longer valid.
|
|
# File 'ext/thread_frame.c'
static VALUE
thread_frame_method(VALUE klass)
{
THREAD_FRAME_SETUP_WITH_ERROR ; \
switch (VM_FRAME_TYPE(tf->cfp)) {
case VM_FRAME_MAGIC_BLOCK:
case VM_FRAME_MAGIC_EVAL:
case VM_FRAME_MAGIC_LAMBDA:
case VM_FRAME_MAGIC_METHOD:
case VM_FRAME_MAGIC_TOP:
if (RUBY_VM_NORMAL_ISEQ_P(tf->cfp->iseq))
return tf->cfp->iseq->name;
else
return Qnil; /* unknown */
case VM_FRAME_MAGIC_CFUNC: {
const char *method_name = rb_id2name(tf->cfp->me->def->original_id);
return rb_str_new2((NULL == method_name) ? "" : method_name );
}
|
- (Object) next
See the above thread_frame_prev comment for what's going on here.
|
|
# File 'ext/thread_frame.c'
static VALUE
thread_frame_next(VALUE klass)
{
rb_control_frame_t *cfp = NULL;
THREAD_FRAME_SETUP_WITH_ERROR ;
cfp = RUBY_VM_NEXT_CONTROL_FRAME(tf->cfp);
if ((void *)(cfp) <= (void *)(tf->th->stack))
return Qnil;
else {
thread_frame_t *next_tf;
VALUE next = thread_frame_alloc(rb_cThreadFrame);
thread_frame_t_alloc(next);
Data_Get_Struct(next, thread_frame_t, next_tf);
next_tf->th = tf->th;
next_tf->cfp = cfp;
COPY_SIGNATURE(tf, cfp);
return next;
}
|
- (Fixnum) pc_offset
Returns the offset inside the iseq or "program-counter offset" or -1 If invalid/unstarted. ThreadFrameError can be raised if the threadframe object is no longer valid.
|
|
# File 'ext/thread_frame.c'
static VALUE
thread_frame_pc_offset(VALUE klass)
{
unsigned long pc;
THREAD_FRAME_SETUP_WITH_ERROR ;
if (RUBY_VM_NORMAL_ISEQ_P(tf->cfp->iseq) &&
(tf->cfp->pc != 0 && tf->cfp->iseq != 0)) {
pc = tf->cfp->pc - tf->cfp->iseq->iseq_encoded;
return INT2FIX(pc);
}
|
- (Object) RubyVM::ThreadFrame
Sets pc to the offset given. WARNING, this is pretty dangerous. You need to set this to a valid instruction offset since little checking is done.
|
|
# File 'ext/thread_frame.c'
static VALUE
thread_frame_set_pc_offset(VALUE klass, VALUE offset_val)
{
int offset;
THREAD_FRAME_SETUP_WITH_ERROR ;
if (!FIXNUM_P(offset_val)) {
rb_raise(rb_eTypeError, "integer argument expected");
}
|
- (Object) RubyVM::ThreadFrame
Returns a RubyVM::ThreadFrame object for the frame prior to the ThreadFrame object or nil if there is none. Setting n=0 just returns the object passed. A negative starts from the end. So prev(-1) is the top frame. Counts outside of the range -stack_size .. stack_size-1 exceed the the range of the stack and return nil.
|
|
# File 'ext/thread_frame.c'
VALUE
thread_frame_prev(int argc, VALUE *argv, VALUE klass)
{
VALUE nv;
int n;
THREAD_FRAME_SETUP_WITH_ERROR ;
rb_scan_args(argc, argv, "01", &nv);
if (Qnil == nv)
n = 1;
else if (!FIXNUM_P(nv)) {
rb_raise(rb_eTypeError, "integer argument expected");
}
|
- (Object) proc
- (Object) return_stop=
- (Boolean) return_stop?
- (Object) self
- (Array, String) RubyVM::ThreadFrame
Returns a tuple representing kind of container, e.g. file eval'd string object, and the name of the container. If file, it would be a file name. If an eval'd string it might be the string.
|
|
# File 'ext/thread_frame.c'
static VALUE
thread_frame_source_container(VALUE klass)
{
VALUE filename = Qnil;
const char *contain_type;
rb_control_frame_t *cfp;
int is_eval = 0;
THREAD_FRAME_SETUP ;
for ( cfp = tf->cfp; cfp && !cfp->iseq && RUBYVM_CFUNC_FRAME_P(cfp);
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp) ) ;
if (cfp->iseq)
filename = cfp->iseq->filename;
else {
if (tf->th->vm->progname)
filename = tf->th->vm->progname;
else
return Qnil;
}
|
- (Array) RubyVM::ThreadFrame
Returns an array of source location positions that match tf.instruction_offset. A source location position is left implementation dependent. It could be line number, a line number and start and end column, or a start line number, start column, end line number, end column.
|
|
# File 'ext/thread_frame.c'
static VALUE
thread_frame_source_location(VALUE klass)
{
rb_control_frame_t *cfp;
THREAD_FRAME_SETUP ;
/* For now, it appears like we have line numbers only when there
is an instruction sequence. The heuristic that is used by
vm_backtrace_each of vm.c seems to be to use the line number of
the closest control frame that has an instruction sequence.
FIXME: investigate whether this is always the most accurate location. If
not, improve.
*/
for ( cfp = tf->cfp; cfp && !cfp->iseq && RUBYVM_CFUNC_FRAME_P(cfp);
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp) ) ;
return (cfp->iseq)
/* NOTE: for now sourceline returns a single int. In the
future it might return an array of ints.
*/
? rb_ary_new3(1, INT2FIX(rb_vm_get_sourceline(cfp)))
: Qnil;
}
|
- (Object) RubyVM::ThreadFrame
Returns a RubyVM object stored at stack position i. The top object is position 0. 1 is the next object.
|
|
# File 'ext/thread_frame.c'
VALUE
thread_frame_sp(VALUE klass, VALUE index)
{
/* handled by THREAD_FRAME_FP_METHOD macro; */
}
|
- (Object) RubyVM::ThreadFrame
Sets VM stack position n to newvalue. The top object is position 0. 1 is the next object.
|
|
# File 'ext/thread_frame.c'
static VALUE
thread_frame_sp_set(VALUE klass, VALUE index, VALUE newvalue)
{
if (!FIXNUM_P(index)) {
rb_raise(rb_eTypeError, "integer argument expected");
}
|
- (FixNum) RubyVM::ThreadFrame
Returns the number of stack or sp entries in the current frame. That is the, number values that have been pushed onto the stack since the current call. This is different than RubyVM::ThreadFrame#stack_size which counts the number of frames in the call stack. nil is returned if there is an error.
|
|
# File 'ext/thread_frame.c'
VALUE
thread_frame_sp_size(VALUE klass)
{
THREAD_FRAME_SETUP_WITH_ERROR ;
return INT2FIX(thread_frame_sp_size_internal(tf));
}
|
- (Fixnum;) RubyVM::ThreadFrame
Returns a count of the number of frames including the current one. ThreadFrame#prev(ThreadFrame#stack_size) = nil ThreadFrame#prev(ThreadFrame#stack_size-1) = top frame
|
|
# File 'ext/thread_frame.c'
static VALUE
thread_frame_stack_size(VALUE klass)
{
THREAD_FRAME_SETUP ;
return INT2FIX(thread_frame_stack_size_internal(tf->cfp, tf->th));
}
|
- (Object) RubyVM::ThreadFrame
Returns the thread object for the thread frame.
|
|
# File 'ext/thread_frame.c'
static VALUE
thread_frame_thread(VALUE klass)
{
THREAD_FRAME_SETUP ;
return tf->th->self;
}
|
- (Object) trace_off=
- (Boolean) trace_off?
- (String) type
Returns the kind of frame. Basically interprets VM_FRAME_MAGIC for tf->cfp->flag
|
|
# File 'ext/thread_frame.c'
static VALUE
thread_frame_type(VALUE klass)
{
THREAD_FRAME_SETUP ;
return rb_str_new2(frame_magic2str(tf->cfp));
}
|