* parse.y (yycompile): disable trace while creating ruby_debug_lines.

[ruby-talk:253586]

* thread.c (ruby_suppress_tracing): new function to call a function
  with suppressing trace.

* lib/debug.rb, lib/tracer.rb: for YARV.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12569 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2007-06-18 07:55:45 +00:00
parent 31345380ac
commit 942a54302d
5 changed files with 107 additions and 98 deletions

View File

@ -1,3 +1,13 @@
Mon Jun 18 16:57:24 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
* parse.y (yycompile): disable trace while creating ruby_debug_lines.
[ruby-talk:253586]
* thread.c (ruby_suppress_tracing): new function to call a function
with suppressing trace.
* lib/debug.rb, lib/tracer.rb: for YARV.
Mon Jun 18 13:54:36 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
* eval.c (ruby_cleanup): return EXIT_FAILURE if any exceptions occured

View File

@ -19,45 +19,6 @@ end
SCRIPT_LINES__ = {} unless defined? SCRIPT_LINES__
class DEBUGGER__
class Mutex
def initialize
@locker = nil
@waiting = []
@locked = false;
end
def locked?
@locked
end
def lock
return if Thread.critical
return if @locker == Thread.current
while (Thread.critical = true; @locked)
@waiting.push Thread.current
Thread.stop
end
@locked = true
@locker = Thread.current
Thread.critical = false
self
end
def unlock
return if Thread.critical
return unless @locked
unless @locker == Thread.current
raise RuntimeError, "unlocked by other"
end
Thread.critical = true
t = @waiting.shift
@locked = false
@locker = nil
Thread.critical = false
t.run if t
self
end
end
MUTEX = Mutex.new
class Context
@ -118,13 +79,14 @@ class Context
end
def check_suspend
return if Thread.critical
while (Thread.critical = true; @suspend_next)
DEBUGGER__.waiting.push Thread.current
@suspend_next = false
Thread.stop
while MUTEX.synchronize {
if @suspend_next
DEBUGGER__.waiting.push Thread.current
@suspend_next = false
true
end
}
end
Thread.critical = false
end
def trace?
@ -790,13 +752,12 @@ class << DEBUGGER__
end
def set_trace( arg )
saved_crit = Thread.critical
Thread.critical = true
make_thread_list
for th, in @thread_list
context(th).set_trace arg
MUTEX.synchronize do
make_thread_list
for th, in @thread_list
context(th).set_trace arg
end
end
Thread.critical = saved_crit
arg
end
@ -805,31 +766,29 @@ class << DEBUGGER__
end
def suspend
saved_crit = Thread.critical
Thread.critical = true
make_thread_list
for th, in @thread_list
next if th == Thread.current
context(th).set_suspend
MUTEX.synchronize do
make_thread_list
for th, in @thread_list
next if th == Thread.current
context(th).set_suspend
end
end
Thread.critical = saved_crit
# Schedule other threads to suspend as soon as possible.
Thread.pass unless Thread.critical
Thread.pass
end
def resume
saved_crit = Thread.critical
Thread.critical = true
make_thread_list
for th, in @thread_list
next if th == Thread.current
context(th).clear_suspend
MUTEX.synchronize do
make_thread_list
for th, in @thread_list
next if th == Thread.current
context(th).clear_suspend
end
waiting.each do |th|
th.run
end
waiting.clear
end
waiting.each do |th|
th.run
end
waiting.clear
Thread.critical = saved_crit
# Schedule other threads to restart as soon as possible.
Thread.pass
end
@ -944,4 +903,7 @@ stdout.printf "Emacs support available.\n\n"
set_trace_func proc { |event, file, line, id, binding, klass, *rest|
DEBUGGER__.context.trace_func event, file, line, id, binding, klass
}
VM::InstructionSequence.compile_option = {
trace_instruction: true
}
end

View File

@ -118,8 +118,8 @@ class Tracer
return unless p.call event, file, line, id, binding, klass
end
saved_crit = Thread.critical
Thread.critical = true
# saved_crit = Thread.critical
# Thread.critical = true
stdout.printf("#%d:%s:%d:%s:%s: %s",
get_thread_no,
file,
@ -127,7 +127,7 @@ class Tracer
klass || '',
EVENT_SYMBOL[event],
get_line(file, line))
Thread.critical = saved_crit
# Thread.critical = saved_crit
end
Single = new

37
parse.y
View File

@ -4584,26 +4584,35 @@ parser_yyerror(struct parser_params *parser, const char *msg)
static void parser_prepare(struct parser_params *parser);
#ifndef RIPPER
VALUE ruby_suppress_tracing(VALUE (*func)(ANYARGS), VALUE arg);
static VALUE
debug_lines(VALUE f)
{
if (rb_const_defined_at(rb_cObject, rb_intern("SCRIPT_LINES__"))) {
VALUE hash = rb_const_get_at(rb_cObject, rb_intern("SCRIPT_LINES__"));
if (TYPE(hash) == T_HASH) {
VALUE fname = rb_str_new2((const char *)f);
VALUE lines = rb_hash_aref(hash, fname);
if (NIL_P(lines)) {
lines = rb_ary_new();
rb_hash_aset(hash, fname, lines);
}
return lines;
}
}
return 0;
}
static NODE*
yycompile(struct parser_params *parser, const char *f, int line)
{
int n;
const char *kcode_save;
if (!compile_for_eval && rb_safe_level() == 0 &&
rb_const_defined(rb_cObject, rb_intern("SCRIPT_LINES__"))) {
VALUE hash, fname;
hash = rb_const_get(rb_cObject, rb_intern("SCRIPT_LINES__"));
if (TYPE(hash) == T_HASH) {
fname = rb_str_new2(f);
ruby_debug_lines = rb_hash_aref(hash, fname);
if (NIL_P(ruby_debug_lines)) {
ruby_debug_lines = rb_ary_new();
rb_hash_aset(hash, fname, ruby_debug_lines);
}
}
if (line > 1) {
if (!compile_for_eval && rb_safe_level() == 0) {
ruby_debug_lines = ruby_suppress_tracing(debug_lines, (VALUE)f);
if (ruby_debug_lines && line > 1) {
VALUE str = rb_str_new(0,0);
n = line - 1;
do {

View File

@ -2789,17 +2789,47 @@ get_event_name(rb_event_flag_t event)
}
}
static void
call_trace_func(rb_event_flag_t event, VALUE proc, VALUE self, ID id, VALUE klass)
VALUE ruby_suppress_tracing(VALUE (*func)(ANYARGS), VALUE arg);
struct call_trace_func_args {
rb_event_flag_t event;
VALUE proc;
VALUE self;
ID id;
VALUE klass;
};
static VALUE
call_trace_proc(VALUE args)
{
rb_thread_t *th = GET_THREAD();
int state, raised;
VALUE eventname = rb_str_new2(get_event_name(event));
struct call_trace_func_args *p = (struct call_trace_func_args *)args;
VALUE eventname = rb_str_new2(get_event_name(p->event));
VALUE filename = rb_str_new2(rb_sourcefile());
int line = rb_sourceline();
return rb_proc_call(p->proc, rb_ary_new3(6,
eventname, filename, INT2FIX(line),
p->id ? ID2SYM(p->id) : Qnil,
p->self ? rb_binding_new() : Qnil,
p->klass ? p->klass : Qnil));
}
static void
call_trace_func(rb_event_flag_t event, VALUE proc, VALUE self, ID id, VALUE klass)
{
struct call_trace_func_args args = {event, proc, self, id, klass};
ruby_suppress_tracing(call_trace_proc, (VALUE)&args);
}
VALUE
ruby_suppress_tracing(VALUE (*func)(ANYARGS), VALUE arg)
{
rb_thread_t *th = GET_THREAD();
int state, raised;
VALUE result = Qnil;
if (th->tracing) {
return;
return Qnil;
}
else {
th->tracing = 1;
@ -2809,11 +2839,7 @@ call_trace_func(rb_event_flag_t event, VALUE proc, VALUE self, ID id, VALUE klas
PUSH_TAG();
if ((state = EXEC_TAG()) == 0) {
proc_invoke(proc, rb_ary_new3(6,
eventname, filename, INT2FIX(line),
id ? ID2SYM(id) : Qnil,
self ? rb_binding_new() : Qnil,
klass ? klass : Qnil), Qundef, 0);
result = (*func)(arg);
}
if (raised) {
@ -2825,6 +2851,8 @@ call_trace_func(rb_event_flag_t event, VALUE proc, VALUE self, ID id, VALUE klas
if (state) {
JUMP_TAG(state);
}
return result;
}
/*