Index: object.c =================================================================== --- object.c (revision 63540) +++ object.c (working copy) @@ -895,7 +895,24 @@ 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 * @@ -4098,6 +4115,7 @@ 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 */ Index: vm.c =================================================================== --- vm.c (revision 63540) +++ vm.c (working copy) @@ -453,6 +453,23 @@ 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 @@ -2840,6 +2857,8 @@ 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); Index: vm_dump.c =================================================================== --- vm_dump.c (revision 63540) +++ vm_dump.c (working copy) @@ -137,6 +137,74 @@ 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) {