Project

General

Profile

Feature #14801 » show_stack.patch

proof-of-concept patch for show_stack method - duerst (Martin Dürst), 06/01/2018 02:03 AM

View differences:

object.c (working copy)
return obj;
}
/*
* call-seq:
* obj.show_stack -> obj
*
* Outputs the current stack to stderr (similar to when there's an internal error).
*
* This method is only expected to work on C Ruby.
*/
void rb_vmdebug_stack_show_raw_current(void); /* sloppy, should move to header file */
static VALUE
rb_obj_show_stack(VALUE obj)
{
rb_vmdebug_stack_show_raw_current();
return obj;
}
/*
* Document-method: inherited
*
......
rb_define_method(rb_mKernel, "kind_of?", rb_obj_is_kind_of, 1);
rb_define_method(rb_mKernel, "is_a?", rb_obj_is_kind_of, 1);
rb_define_method(rb_mKernel, "tap", rb_obj_tap, 0);
rb_define_method(rb_mKernel, "show_stack", rb_obj_show_stack, 0);
rb_define_global_function("sprintf", rb_f_sprintf, -1); /* in sprintf.c */
rb_define_global_function("format", rb_f_sprintf, -1); /* in sprintf.c */
vm.c (working copy)
return hash;
}
/*
* call-seq:
* RubyVM.show_stack -> nil
*
* Outputs the current stack to stderr (similar to when there's an internal error).
*
* This method is only expected to work on C Ruby.
*/
void rb_vmdebug_stack_show_raw_current(void); /* sloppy, should move to header file */
static VALUE
vm_show_stack(int argc, VALUE *argv, VALUE self)
{
rb_vmdebug_stack_show_raw_current();
return Qnil;
}
/* control stack frame */
static void
......
rb_undef_alloc_func(rb_cRubyVM);
rb_undef_method(CLASS_OF(rb_cRubyVM), "new");
rb_define_singleton_method(rb_cRubyVM, "stat", vm_stat, -1);
rb_define_singleton_method(rb_cRubyVM, "show_stack", vm_show_stack, 0);
/* FrozenCore (hidden) */
fcore = rb_class_new(rb_cBasicObject);
vm_dump.c (working copy)
fprintf(stderr, "\n");
}
// new function, to show stack during execution
// modified from rb_vmdebug_stack_dump_raw
void rb_vmdebug_stack_show_raw_current(void)
{
const rb_execution_context_t *ec = GET_EC();
const rb_control_frame_t *cfp = (rb_control_frame_t*) (ec->vm_stack + ec->vm_stack_size) - 1;
const rb_control_frame_t *cfp_end = ec->cfp;
VALUE *sp = cfp_end->sp, *ep;
VALUE *p, *st, *t;
fprintf(stderr, "-- Control Frames "
"-----------------------------------------------\n");
while (cfp > cfp_end) { // skip show_stack method itself
control_frame_dump(ec, cfp);
cfp--;
}
fprintf(stderr, "\n");
fprintf(stderr, "-- Internal Stack ------------\n");
for (p = sp-4, st = ec->vm_stack, cfp = cfp_end+1; p-3 >= ec->vm_stack; p--) {
ep = (VALUE *)cfp->ep;
fprintf(stderr, "%04ld (%p): %016"PRIxVALUE, (long)(p - st), p, *p);
t = (VALUE *)*p;
if (ec->vm_stack <= t && t < sp) {
fprintf(stderr, " (= %ld)", (long)((VALUE *)t - ec->vm_stack));
}
else if (p == ep) {
fprintf(stderr, " (flags) <- Environment Pointer");
fprintf(stderr, " (%ld)", ((rb_control_frame_t *)(ec->vm_stack + ec->vm_stack_size) - cfp));
}
else if (p == ep-1) {
fprintf(stderr, " (specval)");
}
else if (p == ep-2) {
fprintf(stderr, " (me_cref)");
cfp++;
}
else {
VALUE klass = rb_obj_class(*p);
VALUE val = rb_mod_name(klass);
if (!NIL_P(val)) {
fprintf(stderr, " %s", RSTRING_PTR(val));
if (FIXNUM_P(*p))
fprintf(stderr, ": %d", FIX2INT(*p));
else if (RB_TYPE_P(*p, T_FLOAT))
fprintf(stderr, ": %g", RFLOAT_VALUE(*p));
else if (klass == rb_cFalseClass)
fprintf(stderr, ": false");
else if (klass == rb_cTrueClass)
fprintf(stderr, ": true");
else if (klass == rb_cNilClass)
fprintf(stderr, ": nil");
else if (klass == rb_cSymbol)
fprintf(stderr, ": :%s", RSTRING_PTR(rb_sym_to_s(*p)));
else if (klass == rb_cString && RSTRING_LEN(*p)<= 20)
fprintf(stderr, ": '%s'", RSTRING_PTR(*p));
}
}
if (p == (VALUE *)cfp->sp)
fprintf(stderr, " <- Stack Pointer (%ld)", ((rb_control_frame_t *)(ec->vm_stack + ec->vm_stack_size) - cfp));
fprintf(stderr, "\n");
}
fprintf(stderr, "\n");
}
void
rb_vmdebug_stack_dump_raw(const rb_execution_context_t *ec, const rb_control_frame_t *cfp)
{
    (1-1/1)