From: Markus Date: 2004-10-27T01:58:51+09:00 Subject: Re: Errors in line numbers reported? This seems to be along the lines I was thinking, but there seems to be more to it than I was imagining, and I do not understand all of it. Why is the interaction with the GC needed? Wouldn't it be enough to allocate them and keep them around forever? I was thinking it could be done by patching node.h (to add and adjust macros), eval.c (to use them), and parse.y, to make a small struct with int line_number_offset and char *file_name to store in the RNODEs in place of nd_file. The main complexity would be making a new current struct any time a RNODE was created and ruby_sourceline - current->line_number_offset >= 8*1024 Is there a reason that I am not seeing why this would not work? -- Markus On Tue, 2004-10-26 at 08:57, nobu.nokada@softhome.net wrote: > Hi, > > At Tue, 26 Oct 2004 11:27:59 +0900, > Hal Fulton wrote in [ruby-talk:117698]: > > > |Matz: If you're interested, I'll send you a tarball. > > > > > > Send me, unless the source file is larger than 8191 lines. > > > It's implementation restriction. > > > > OK, I never knew that. > > > > The file is 11,756 lines (down from 22,000). > > Well, 2,097,151 lines are enough? > > > Index: gc.c > =================================================================== > RCS file: /cvs/ruby/src/ruby/gc.c,v > retrieving revision 1.188 > diff -U2 -p -d -r1.188 gc.c > --- gc.c 6 Oct 2004 07:40:04 -0000 1.188 > +++ gc.c 26 Oct 2004 15:16:41 -0000 > @@ -509,7 +509,69 @@ init_mark_stack() > > #define MARK_STACK_EMPTY (mark_stack_ptr == mark_stack) > - > + > static st_table *source_filenames; > > +#ifdef NODE_SEGMENTED_LINENO > + > +static int > +srcfile_cmp(s1, s2) > + const char *s1, *s2; > +{ > + int ret = strcmp(s1, s2); > + if (ret == 0) return 0; > + return s1[srcfile_lineno - srcfile_offset] > + - s2[srcfile_lineno - srcfile_offset]; > +} > + > +int strhash _((const char *)); > + > +static int > +srcfile_hash(s) > + const char *s; > +{ > + return strhash(s) ^ s[srcfile_lineno - srcfile_offset]; > +} > + > +static struct st_hash_type type_srchash = { > + srcfile_cmp, > + srcfile_hash, > +}; > + > +#define init_srcfile_table() st_init_table(&type_srchash) > + > +char * > +rb_source_filenameline(f, n) > + const char *f; > + unsigned int n; > +{ > + char *name, *ptr; > + long len = strlen(f) + 1; > + > + ptr = ALLOC_N(char, len + srcfile_offset); > + MEMCPY(ptr + srcfile_offset, f, char, len); > + f = ptr + srcfile_offset; > + ptr[srcfile_lineno] = (char)(n >> (sizeof(NODE*)*CHAR_BIT-NODE_LSHIFT)); > + > + if (!st_lookup(source_filenames, (st_data_t)f, (st_data_t *)&name)) { > + name = ptr; > + ptr[srcfile_gcmark] = 0; > + ptr += srcfile_offset; > + st_add_direct(source_filenames, (st_data_t)ptr, (st_data_t)name); > + return ptr; > + } > + xfree(ptr); > + return name + srcfile_offset; > +} > + > +char * > +rb_source_filename(f) > + const char *f; > +{ > + return rb_source_filenameline(f, 0); > +} > + > +#else > +#define init_srcfile_table() st_init_strtable() > + > char * > rb_source_filename(f) > @@ -520,12 +582,15 @@ rb_source_filename(f) > if (!st_lookup(source_filenames, (st_data_t)f, (st_data_t *)&name)) { > long len = strlen(f) + 1; > - char *ptr = name = ALLOC_N(char, len + 1); > - *ptr++ = 0; > + char *ptr = name = ALLOC_N(char, len + srcfile_offset); > + ptr[srcfile_gcmark] = 0; > + ptr += srcfile_offset; > MEMCPY(ptr, f, char, len); > st_add_direct(source_filenames, (st_data_t)ptr, (st_data_t)name); > return ptr; > } > - return name + 1; > + return name + srcfile_offset; > } > +#endif > + > > static void > @@ -534,5 +599,5 @@ mark_source_filename(f) > { > if (f) { > - f[-1] = 1; > + f[srcfile_gcmark - srcfile_offset] = 1; > } > } > @@ -542,10 +607,10 @@ sweep_source_filename(key, value) > char *key, *value; > { > - if (*value) { > - *value = 0; > + if (value[srcfile_gcmark]) { > + value[srcfile_gcmark] = 0; > return ST_CONTINUE; > } > else { > - free(value); > + xfree(value); > return ST_DELETE; > } > @@ -1922,5 +1987,5 @@ Init_GC() > finalizers = rb_ary_new(); > > - source_filenames = st_init_strtable(); > + source_filenames = init_srcfile_table(); > > nomem_error = rb_exc_new2(rb_eNoMemError, "failed to allocate memory"); > Index: intern.h > =================================================================== > RCS file: /cvs/ruby/src/ruby/intern.h,v > retrieving revision 1.156 > diff -U2 -p -d -r1.156 intern.h > --- intern.h 6 Oct 2004 07:40:04 -0000 1.156 > +++ intern.h 26 Oct 2004 15:21:45 -0000 > @@ -239,4 +239,5 @@ NORETURN(void rb_memerror __((void))); > int ruby_stack_check _((void)); > int ruby_stack_length _((VALUE**)); > +char *rb_source_filenameline _((const char*, unsigned int)); > char *rb_source_filename _((const char*)); > void rb_gc_mark_locations _((VALUE*, VALUE*)); > Index: node.h > =================================================================== > RCS file: /cvs/ruby/src/ruby/node.h,v > retrieving revision 1.57 > diff -U2 -p -d -r1.57 node.h > --- node.h 2 Oct 2004 11:34:13 -0000 1.57 > +++ node.h 26 Oct 2004 15:17:03 -0000 > @@ -164,8 +164,26 @@ typedef struct RNode { > > #define NODE_LSHIFT (FL_USHIFT+8) > -#define NODE_LMASK (((long)1<<(sizeof(NODE*)*CHAR_BIT-NODE_LSHIFT))-1) > -#define nd_line(n) ((unsigned int)(((RNODE(n))->flags>>NODE_LSHIFT)&NODE_LMASK)) > -#define nd_set_line(n,l) \ > +#define NODE_LBITS (SIZEOF_VOIDP*CHAR_BIT-NODE_LSHIFT) > +#define NODE_LMASK (((long)1< +#define NODE_SEGMENTED_LINENO (NODE_LBITS > 20) > + > +enum { > + srcfile_gcmark, > +#ifdef NODE_SEGMENTED_LINENO > + srcfile_lineno, > +#endif > + srcfile_offset > +}; > + > +#define nd_line_low(n) ((unsigned int)(((RNODE(n))->flags>>NODE_LSHIFT)&NODE_LMASK)) > +#define nd_set_line_low(n,l) \ > RNODE(n)->flags=((RNODE(n)->flags&~(-1< +#ifdef NODE_SEGMENTED_LINENO > +#define nd_line(n) rb_node_line(n) > +#define nd_set_line(n,l) rb_node_set_line(n,l) > +#else > +#define nd_line(n) nd_line_low(n) > +#define nd_set_line(n,l) nd_set_line_low(n,l) > +#endif > > #define nd_head u1.node > @@ -355,4 +373,6 @@ NODE *rb_compile_file _((const char*, VA > void rb_add_method _((VALUE, ID, NODE *, int)); > NODE *rb_node_newnode _((enum node_type,VALUE,VALUE,VALUE)); > +unsigned int rb_node_line _((NODE *)); > +void rb_node_set_line _((NODE *, unsigned int)); > > NODE* rb_method_node _((VALUE klass, ID id)); > Index: parse.y > =================================================================== > RCS file: /cvs/ruby/src/ruby/parse.y,v > retrieving revision 1.353 > diff -U2 -p -d -r1.353 parse.y > --- parse.y 20 Oct 2004 15:44:05 -0000 1.353 > +++ parse.y 26 Oct 2004 15:32:09 -0000 > @@ -6456,4 +6456,30 @@ yylex(p) > > #ifndef RIPPER > +#ifdef NODE_SEGMENTED_LINENO > +unsigned int > +rb_node_line(node) > + NODE *node; > +{ > + unsigned int l = nd_line_low(node); > + const char *file = node->nd_file; > + if (file) { > + l |= (unsigned char)file[srcfile_lineno-srcfile_offset] << NODE_LBITS; > + } > + return l; > +} > + > +void > +rb_node_set_line(node, line) > + NODE *node; > + unsigned int line; > +{ > + const char *file = node->nd_file; > + if (file) { > + node->nd_file = rb_source_filenameline(file, line); > + } > + nd_set_line_low(node, line); > +} > +#endif > + > NODE* > rb_node_newnode(type, a0, a1, a2) > @@ -6465,6 +6491,6 @@ rb_node_newnode(type, a0, a1, a2) > n->flags |= T_NODE; > nd_set_type(n, type); > - nd_set_line(n, ruby_sourceline); > n->nd_file = ruby_sourcefile; > + nd_set_line(n, ruby_sourceline); > > n->u1.value = a0; > Index: st.c > =================================================================== > RCS file: /cvs/ruby/src/ruby/st.c,v > retrieving revision 1.30 > diff -U2 -p -d -r1.30 st.c > --- st.c 23 Sep 2004 00:51:31 -0000 1.30 > +++ st.c 26 Oct 2004 15:31:15 -0000 > @@ -42,5 +42,5 @@ static struct st_hash_type type_numhash > > /* extern int strcmp(const char *, const char *); */ > -static int strhash(const char *); > +int strhash(const char *); > static struct st_hash_type type_strhash = { > strcmp, > @@ -530,5 +530,5 @@ st_foreach(table, func, arg) > } > > -static int > +int > strhash(string) > register const char *string; >