'unexpected return' caused by extension

N

Nathaniel Talbott

This is a multi-part message in MIME format.

------=_NextPart_000_003F_01C38F80.53964A10
Content-Type: text/plain;
charset="us-ascii"
Content-Transfer-Encoding: 7bit

I'm writing my first (useful) Ruby extension, and I'm having issues. I'm
sure it's just a combination of my lack of C knowledge and lack of Ruby
knowledge, but I'd be extremely grateful for any pointers you might have.

Basically, I'm trying to write a better, faster profiler. I've attached all
of the interesting bits. When I run this on the tests from the most recent
Ruby (actually, just trying to get help!), I get the following error:

ntalbott@solomon:~/cvs/ruby/test$ ruby -v -I ~/nprof -rnprofit runner.rb
--help
/usr/local/lib/ruby/1.8/test/unit/autorunner.rb:10: unexpected return
ruby 1.8.0 (2003-10-10) [i686-linux]

Running it without the extension works as expected. I'm sure I'm doing
something stupid... I promise to slap myself on the forehead when someone
shows me what it is.

Also, if you have any suggests regarding my C and/or Ruby/C style, please
let me know. I'm looking to improve as much as possible.

Thanks,


Nathaniel

<:((><

------=_NextPart_000_003F_01C38F80.53964A10
Content-Type: application/octet-stream;
name="nprofit.rb"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="nprofit.rb"

require 'nprof'=0A=
=0A=
n =3D NProf.new=0A=
at_exit {=0A=
set_trace_func(nil)=0A=
#n.print_report=0A=
}=0A=
set_trace_func(n.method:)callback).to_proc)=0A=

------=_NextPart_000_003F_01C38F80.53964A10
Content-Type: application/octet-stream;
name="nprof.rb"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="nprof.rb"

require 'nprofext'=0A=
=0A=
class NProf=0A=
class MethodInfo=0A=
attr_reader :calls, :children=0A=
=0A=
def name=0A=
sep =3D (@klass.kind_of?(Module) ? "." : "#")=0A=
"#@klass#{sep}#@id"=0A=
end=0A=
=0A=
def utime=0A=
@times.utime=0A=
end=0A=
=0A=
def stime=0A=
@times.stime=0A=
end=0A=
end=0A=
=0A=
COLUMN_SEPARATOR =3D " "=0A=
def print_report(out=3DSTDOUT)=0A=
out.puts ["calls", "utime", "stime", "child_count", =
"name"].join(COLUMN_SEPARATOR)=0A=
@method_info.values.each do |m|=0A=
out.printf((["%5d", "%5.2f", "%5.2f", "%11d", =
"%s\n"].join(COLUMN_SEPARATOR)), m.calls, m.utime, m.stime, =
m.children.size, m.name)=0A=
end=0A=
end=0A=
end=0A=

------=_NextPart_000_003F_01C38F80.53964A10
Content-Type: application/octet-stream;
name="nprofext.c"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="nprofext.c"

#include "ruby.h"=0A=
=0A=
/*=0A=
#define DEBUG(message) printf(message)=0A=
#define DEBUG_P(value) rb_p(value)=0A=
=0A=
#define DEBUG(message) =0A=
#define DEBUG_P(value) =0A=
*/=0A=
=0A=
VALUE cNProf;=0A=
VALUE cNProf_MethodInfo;=0A=
=0A=
static VALUE mi_initialize(VALUE self, VALUE klass, VALUE id) {=0A=
VALUE S_Tms =3D rb_const_get(rb_cStruct, rb_intern("Tms"));=0A=
=0A=
rb_iv_set(self, "@klass", klass);=0A=
rb_iv_set(self, "@id", id);=0A=
rb_iv_set(self, "@times", rb_struct_new(S_Tms, =
rb_float_new((double)0), rb_float_new((double)0)));=0A=
rb_iv_set(self, "@children_times", rb_struct_new(S_Tms, =
rb_float_new((double)0), rb_float_new((double)0)));=0A=
rb_iv_set(self, "@children", rb_hash_new());=0A=
rb_iv_set(self, "@calls", INT2FIX(0));=0A=
}=0A=
=0A=
double mi_sub_times(VALUE first, VALUE second) {=0A=
double utime, stime;=0A=
VALUE difference;=0A=
VALUE name =3D rb_str_new2("utime");=0A=
utime =3D NUM2DBL(rb_struct_aref(first, name)) - =
NUM2DBL(rb_struct_aref(second, name));=0A=
name =3D rb_str_new2("stime");=0A=
stime =3D NUM2DBL(rb_struct_aref(first, name)) - =
NUM2DBL(rb_struct_aref(second, name));=0A=
difference =3D rb_struct_new(rb_const_get(rb_cStruct, =
rb_intern("Tms")), rb_float_new(utime), rb_float_new(stime), =
rb_float_new((double)0), rb_float_new((double)0));=0A=
return difference;=0A=
}=0A=
=0A=
double mi_add_times(VALUE first, VALUE second) {=0A=
double utime, stime;=0A=
VALUE name =3D rb_str_new2("utime");=0A=
utime =3D NUM2DBL(rb_struct_aref(first, name)) + =
NUM2DBL(rb_struct_aref(second, name));=0A=
name =3D rb_str_new2("stime");=0A=
stime =3D NUM2DBL(rb_struct_aref(first, name)) + =
NUM2DBL(rb_struct_aref(second, name));=0A=
return rb_struct_new(rb_const_get(rb_cStruct, rb_intern("Tms")), =
rb_float_new(utime), rb_float_new(stime), rb_float_new((double)0), =
rb_float_new((double)0));=0A=
}=0A=
=0A=
void mi_add_in_times(VALUE mi, VALUE difference) {=0A=
rb_iv_set(mi, "@times", mi_add_times(rb_iv_get(mi, "@times"), =
difference));=0A=
}=0A=
=0A=
void mi_finish_child(VALUE parent, VALUE child_key, VALUE child_times) {=0A=
rb_iv_set(parent, "@children_times", mi_add_times(rb_iv_get(parent, =
"@children_times"), child_times));=0A=
rb_hash_aset(rb_iv_get(parent, "@children"), child_key, Qtrue);=0A=
}=0A=
=0A=
static VALUE nprof_initialize(VALUE self) {=0A=
rb_iv_set(self, "@stack", rb_ary_new());=0A=
rb_iv_set(self, "@method_info", rb_hash_new());=0A=
}=0A=
=0A=
static VALUE nprof_rattr_stack(VALUE self) {=0A=
return rb_iv_get(self, "@stack");=0A=
}=0A=
=0A=
static VALUE nprof_rattr_method_info(VALUE self) {=0A=
return rb_iv_get(self, "@method_info");=0A=
}=0A=
=0A=
VALUE nprof_start(VALUE args) {=0A=
VALUE self =3D rb_ary_entry(args, 0);=0A=
VALUE klass =3D rb_ary_entry(args, 1);=0A=
VALUE id =3D rb_ary_entry(args, 2);=0A=
VALUE stack =3D rb_iv_get(self, "@stack");=0A=
VALUE now =3D rb_proc_times(rb_mProcess);=0A=
VALUE method_info_hash, method_info_key, method_info, ary;=0A=
=0A=
ary =3D rb_ary_entry(stack, RARRAY(stack)->len - 1);=0A=
=0A=
method_info_hash =3D rb_iv_get(self, "@method_info");=0A=
method_info_key =3D rb_ary_new3(2, klass, id);=0A=
method_info =3D rb_hash_aref(method_info_hash, method_info_key);=0A=
if(!RTEST(method_info)) {=0A=
method_info =3D rb_funcall(cNProf_MethodInfo, rb_intern("new"), 2, =
klass, id);=0A=
rb_hash_aset(method_info_hash, method_info_key, method_info);=0A=
}=0A=
rb_iv_set(method_info, "@calls", =
INT2FIX(NUM2INT(rb_iv_get(method_info, "@calls")) + 1));=0A=
rb_ary_push(stack, rb_ary_new3(2, method_info, now));=0A=
return Qnil;=0A=
}=0A=
=0A=
VALUE nprof_finish(VALUE args) {=0A=
VALUE self =3D rb_ary_entry(args, 0);=0A=
VALUE klass =3D rb_ary_entry(args, 1);=0A=
VALUE id =3D rb_ary_entry(args, 2);=0A=
VALUE stack =3D rb_iv_get(self, "@stack");=0A=
VALUE now =3D rb_proc_times(rb_mProcess);=0A=
VALUE method_info_key, method_info, ary, then, difference;=0A=
=0A=
ary =3D rb_ary_pop(stack);=0A=
if(!RTEST(ary))=0A=
return Qnil;=0A=
=0A=
method_info =3D rb_ary_entry(ary, 0);=0A=
then =3D rb_ary_entry(ary, 1);=0A=
=0A=
difference =3D mi_sub_times(now, then);=0A=
mi_add_in_times(method_info, difference);=0A=
=0A=
ary =3D rb_ary_entry(stack, RARRAY(stack)->len - 1);=0A=
if(RTEST(ary)) {=0A=
method_info_key =3D rb_ary_new3(2, klass, id);=0A=
mi_finish_child(rb_ary_entry(ary, 0), method_info_key, difference);=0A=
}=0A=
return Qnil;=0A=
}=0A=
=0A=
VALUE nprof_err(VALUE args, VALUE error) {=0A=
rb_funcall(rb_mKernel, rb_intern("set_trace_func"), 1, Qnil);=0A=
rb_p(args);=0A=
rb_p(error);=0A=
return Qnil;=0A=
}=0A=
=0A=
static VALUE nprof_callback(VALUE self, VALUE event, VALUE file, VALUE =
line, VALUE id, VALUE binding, VALUE klass) {=0A=
char* event_string =3D STR2CSTR(event);=0A=
VALUE args, eargs;=0A=
=0A=
if(!strcmp(event_string, "call") || !strcmp(event_string, "c-call")) {=0A=
args =3D rb_ary_new3(3, self, klass, id);=0A=
eargs =3D rb_ary_new3(3, line, klass, id);=0A=
rb_rescue(nprof_start, args, nprof_err, eargs);=0A=
} else if(!strcmp(event_string, "return") || !strcmp(event_string, =
"c-return")) {=0A=
args =3D rb_ary_new3(3, self, klass, id);=0A=
eargs =3D rb_ary_new3(3, line, klass, id);=0A=
rb_rescue(nprof_finish, args, nprof_err, eargs);=0A=
}=0A=
=0A=
return Qnil;=0A=
}=0A=
=0A=
void Init_nprofext() {=0A=
cNProf =3D rb_define_class("NProf", rb_cObject);=0A=
rb_define_method(cNProf, "initialize", nprof_initialize, 0);=0A=
rb_define_method(cNProf, "stack", nprof_rattr_stack, 0);=0A=
rb_define_method(cNProf, "method_info", nprof_rattr_method_info, 0);=0A=
rb_define_method(cNProf, "callback", nprof_callback, 6);=0A=
=0A=
cNProf_MethodInfo =3D rb_define_class_under(cNProf, "MethodInfo", =
rb_cObject);=0A=
rb_define_method(cNProf_MethodInfo, "initialize", mi_initialize, 2);=0A=
}=0A=

------=_NextPart_000_003F_01C38F80.53964A10
Content-Type: application/octet-stream;
name="extconf.rb"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="extconf.rb"

require 'mkmf'=0A=
=0A=
create_makefile("nprofext")=0A=

------=_NextPart_000_003F_01C38F80.53964A10--
 
Y

Yukihiro Matsumoto

Hi,

In message "'unexpected return' caused by extension"

|I'm writing my first (useful) Ruby extension, and I'm having issues. I'm
|sure it's just a combination of my lack of C knowledge and lack of Ruby
|knowledge, but I'd be extremely grateful for any pointers you might have.
|
|Basically, I'm trying to write a better, faster profiler. I've attached all
|of the interesting bits. When I run this on the tests from the most recent
|Ruby (actually, just trying to get help!), I get the following error:
|
| ntalbott@solomon:~/cvs/ruby/test$ ruby -v -I ~/nprof -rnprofit runner.rb
|--help
| /usr/local/lib/ruby/1.8/test/unit/autorunner.rb:10: unexpected return
| ruby 1.8.0 (2003-10-10) [i686-linux]
|
|Running it without the extension works as expected. I'm sure I'm doing
|something stupid... I promise to slap myself on the forehead when someone
|shows me what it is.

It's a bug. I fixed it in the latest CVS.

matz.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top