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<<NODE_LBITS)-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<<NODE_LSHIFT))|(((l)&NODE_LMASK)<<NODE_LSHIFT)) +#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;
-- Nobu Nakada