diff --git a/src/builtin_functions.c b/src/builtin_functions.c index b55450f28238811ca2ae6a46e978ed34404a8b96..e97d0fd7b84936ca7d5af8f7c33fc6b3ac3ae98d 100644 --- a/src/builtin_functions.c +++ b/src/builtin_functions.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: builtin_functions.c,v 1.100 1998/04/17 05:08:01 hubbe Exp $"); +RCSID("$Id: builtin_functions.c,v 1.101 1998/04/24 00:32:08 hubbe Exp $"); #include "interpret.h" #include "svalue.h" #include "pike_macros.h" @@ -1406,8 +1406,7 @@ void f_column(INT32 args) #ifdef DEBUG void f__verify_internals(INT32 args) { - INT32 tmp; - tmp=d_flag; + INT32 tmp=d_flag; d_flag=0x7fffffff; do_debug(); d_flag=tmp; @@ -2775,8 +2774,8 @@ void init_builtin_efuns(void) add_efun("gc",f_gc,"function(:int)",OPT_SIDE_EFFECT); add_efun("version", f_version, "function(:string)", OPT_TRY_OPTIMIZE); - add_efun("encode_value", f_encode_value, "function(mixed:string)", OPT_TRY_OPTIMIZE); - add_efun("decode_value", f_decode_value, "function(string:mixed)", OPT_TRY_OPTIMIZE); + add_efun("encode_value", f_encode_value, "function(mixed,void|object:string)", OPT_TRY_OPTIMIZE); + add_efun("decode_value", f_decode_value, "function(string,void|object:mixed)", OPT_TRY_OPTIMIZE); add_efun("object_variablep", f_object_variablep, "function(object,string:int)", OPT_EXTERNAL_DEPEND); add_function("diff",f_diff,"function(array,array:array(array))",OPT_TRY_OPTIMIZE); diff --git a/src/compilation.h b/src/compilation.h index dfac0397e4b84e8d1edcbfb0baa2ba7f1cb5d272..c69032220b838eea8b5339e67723c7c1fee6fdb4 100644 --- a/src/compilation.h +++ b/src/compilation.h @@ -1,5 +1,5 @@ /* - * $Id: compilation.h,v 1.8 1998/03/28 15:38:36 grubba Exp $ + * $Id: compilation.h,v 1.9 1998/04/24 00:32:08 hubbe Exp $ * * Compilator state push / pop operator construction file * @@ -86,11 +86,12 @@ ZMEMBER(INT32,last_pc) ZMEMBER(int,num_parse_error) ZMEMBER(struct compiler_frame *,compiler_frame) - ZMEMBER(dynamic_buffer,used_modules) + ZMEMBER(INT32,num_used_modules) IMEMBER(int,comp_stackp) IMEMBER(int,compiler_pass) ZMEMBER(int,local_class_counter) ZMEMBER(int,catch_level) + ZMEMBER(struct mapping *,module_index_cache) SEND #undef PCODE diff --git a/src/encode.c b/src/encode.c index b6e40c838899904e4d11a17ec1b0f828247d3ec8..dbfacd50d7d46219addb11758a3ffd97c3435f46 100644 --- a/src/encode.c +++ b/src/encode.c @@ -17,8 +17,10 @@ #include "error.h" #include "operators.h" #include "builtin_functions.h" +#include "module_support.h" +#include "fsort.h" -RCSID("$Id: encode.c,v 1.19 1998/04/20 18:53:15 grubba Exp $"); +RCSID("$Id: encode.c,v 1.20 1998/04/24 00:32:08 hubbe Exp $"); #ifdef _AIX #include <net/nh.h> @@ -51,16 +53,31 @@ double LDEXP(double x, int exp) } #endif +#ifdef DEBUG +#define encode_value2 encode_value2_ +#define decode_value2 decode_value2_ +#endif + + struct encode_data { + struct object *codec; struct svalue counter; struct mapping *encoded; dynamic_buffer buf; }; +static void encode_value2(struct svalue *val, struct encode_data *data); + #define addstr(s, l) low_my_binary_strcat((s), (l), &(data->buf)) #define addchar(t) low_my_putchar((t),&(data->buf)) +#define adddata(S) do { \ + code_entry(T_STRING, (S)->len, data); \ + addstr((char *)((S)->str),(S)->len); \ +}while(0) + +#define adddata2(s,l) addstr((char *)(s),(l) * sizeof(s[0])); /* Current encoding: �ik0 */ #define T_AGAIN 15 @@ -110,9 +127,89 @@ static void code_entry(int type, INT32 num, struct encode_data *data) } } -#ifdef DEBUG -#define encode_value2 encode_value2_ -#endif + +static void code_number(INT32 num, struct encode_data *data) +{ + code_entry(num & 15, num >> 4, data); +} + +static int encode_type(char *t, struct encode_data *data) +{ + char *q=t; +one_more_type: + addchar(EXTRACT_UCHAR(t)); + switch(EXTRACT_UCHAR(t++)) + { + default: + fatal("error in type string.\n"); + /*NOTREACHED*/ + + break; + + case T_ASSIGN: + addchar(EXTRACT_UCHAR(t++)); + goto one_more_type; + + case T_FUNCTION: + while(EXTRACT_UCHAR(t)!=T_MANY) + t+=encode_type(t, data); + addchar(EXTRACT_UCHAR(t++)); + + case T_MAPPING: + case T_OR: + case T_AND: + t+=encode_type(t, data); + + case T_ARRAY: + case T_MULTISET: + case T_NOT: + goto one_more_type; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case T_INT: + case T_FLOAT: + case T_STRING: + case T_PROGRAM: + case T_MIXED: + case T_VOID: + case T_UNKNOWN: + break; + + case T_OBJECT: + { + INT32 x; + addchar(EXTRACT_UCHAR(t++)); + x=EXTRACT_INT(t); + t+=sizeof(INT32); + if(x) + { + struct program *p=id_to_program(x); + if(p) + { + ref_push_program(p); + }else{ + push_int(0); + } + }else{ + push_int(0); + } + encode_value2(sp-1, data); + pop_stack(); + break; + } + } + return t-q; +} + static void encode_value2(struct svalue *val, struct encode_data *data) @@ -126,7 +223,8 @@ static void encode_value2(struct svalue *val, struct encode_data *data) INT32 i; struct svalue *tmp; - if((val->type == T_OBJECT || val->type==T_FUNCTION) && !val->u.object->prog) + if((val->type == T_OBJECT || (val->type==T_FUNCTION && \ + val->subtype!=FUNCTION_BUILTIN)) && !val->u.object->prog) val=&dested; if((tmp=low_mapping_lookup(data->encoded, val))) @@ -209,22 +307,22 @@ static void encode_value2(struct svalue *val, struct encode_data *data) case T_OBJECT: check_stack(1); push_svalue(val); - APPLY_MASTER("nameof", 1); + apply(data->codec, "nameof", 1); switch(sp[-1].type) { case T_INT: if(sp[-1].subtype == NUMBER_UNDEFINED) { - struct svalue s; - s.type = T_PROGRAM; - s.u.program=val->u.object->prog; - pop_stack(); + push_svalue(val); + f_object_program(1); + code_entry(val->type, 1,data); - encode_value2(&s, data); + encode_value2(sp-1, data); + pop_stack(); push_svalue(val); - APPLY_MASTER("encode_object",1); + apply(data->codec,"encode_object",1); break; } /* FALL THROUGH */ @@ -241,7 +339,7 @@ static void encode_value2(struct svalue *val, struct encode_data *data) case T_FUNCTION: check_stack(1); push_svalue(val); - APPLY_MASTER("nameof", 1); + apply(data->codec,"nameof", 1); if(sp[-1].type == T_INT && sp[-1].subtype==NUMBER_UNDEFINED) { if(val->subtype != FUNCTION_BUILTIN) @@ -282,15 +380,92 @@ static void encode_value2(struct svalue *val, struct encode_data *data) case T_PROGRAM: + { + int d; check_stack(1); push_svalue(val); - APPLY_MASTER("nameof", 1); + apply(data->codec,"nameof", 1); if(sp[-1].type == val->type) error("Error in master()->nameof(), same type returned.\n"); - code_entry(val->type, 0,data); - encode_value2(sp-1, data); + if(sp[-1].type == T_INT && sp[-1].subtype == NUMBER_UNDEFINED) + { + INT32 e; + struct program *p=val->u.program; + if(p->init || p->exit || p->gc_marked || p->gc_check || + (p->flags & PROGRAM_HAS_C_METHODS)) + error("Cannot encode C programs.\n"); + code_entry(val->type, 1,data); + code_number(p->flags,data); + code_number(p->storage_needed,data); + code_number(p->timestamp.tv_sec,data); + code_number(p->timestamp.tv_usec,data); + +#define FOO(X,Y,Z) \ + code_number( p->num_##Z, data); +#include "program_areas.h" + + adddata2(p->program, p->num_program); + adddata2(p->linenumbers, p->num_linenumbers); + + for(d=0;d<p->num_identifier_index;d++) + code_number(p->identifier_index[d],data); + + for(d=0;d<p->num_variable_index;d++) + code_number(p->variable_index[d],data); + + for(d=0;d<p->num_identifier_references;d++) + { + code_number(p->identifier_references[d].inherit_offset,data); + code_number(p->identifier_references[d].identifier_offset,data); + code_number(p->identifier_references[d].id_flags,data); + } + + for(d=0;d<p->num_strings;d++) adddata(p->strings[d]); + + for(d=1;d<p->num_inherits;d++) + { + code_number(p->inherits[d].inherit_level,data); + code_number(p->inherits[d].identifier_level,data); + code_number(p->inherits[d].parent_offset,data); + code_number(p->inherits[d].storage_offset,data); + + if(p->inherits[d].parent) + { + ref_push_object(p->inherits[d].parent); + sp[-1].subtype=p->inherits[d].parent_identifier; + sp[-1].type=T_FUNCTION; + }else if(p->inherits[d].prog){ + ref_push_program(p->inherits[d].prog); + }else{ + push_int(0); + } + encode_value2(sp-1,data); + pop_stack(); + + adddata(p->inherits[d].name); + } + + for(d=0;d<p->num_identifiers;d++) + { + adddata(p->identifiers[d].name); + encode_type(p->identifiers[d].type->str, data); + code_number(p->identifiers[d].identifier_flags,data); + code_number(p->identifiers[d].run_time_type,data); + code_number(p->identifiers[d].func.offset,data); + } + + for(d=0;d<p->num_constants;d++) + encode_value2(p->constants+d, data); + + for(d=0;d<NUM_LFUNS;d++) + code_number(p->lfuns[d], data); + }else{ + code_entry(val->type, 0,data); + encode_value2(sp-1, data); + } pop_stack(); break; + } } } @@ -305,11 +480,19 @@ void f_encode_value(INT32 args) ONERROR tmp; struct encode_data d, *data; data=&d; + + check_all_args("encode_value", args, BIT_MIXED, BIT_VOID | BIT_OBJECT, 0); initialize_buf(&data->buf); data->encoded=allocate_mapping(128); data->counter.type=T_INT; data->counter.u.integer=COUNTER_START; + if(args > 1) + { + data->codec=sp[1-args].u.object; + }else{ + data->codec=get_master(); + } SET_ONERROR(tmp, free_encode_data, data); addstr("\266ke0", 4); @@ -317,6 +500,7 @@ void f_encode_value(INT32 args) UNSET_ONERROR(tmp); free_mapping(data->encoded); + pop_n_elems(args); push_string(low_free_buf(&data->buf)); } @@ -328,8 +512,12 @@ struct decode_data INT32 ptr; struct mapping *decoded; struct svalue counter; + struct object *codec; + int pickyness; }; +static void decode_value2(struct decode_data *data); + static int my_extract_char(struct decode_data *data) { if(data->ptr >= data->len) @@ -351,9 +539,124 @@ static int my_extract_char(struct decode_data *data) } \ if(what & T_NEG) num=~num -#ifdef DEBUG -#define decode_value2 decode_value2_ -#endif + +#define decode_entry(X,Y,Z) \ + do { \ + INT32 what, e, num; \ + DECODE(); \ + if((what & T_MASK) != (X)) error("Failed to decode, wrong bits (%d).\n", what & T_MASK);\ + (Y)=num; \ + } while(0); + +#define getdata2(S,L) do { \ + if(data->ptr + (long)(sizeof(S[0])*(L)) > data->len) \ + error("Failed to decode string. (string range error)\n"); \ + MEMCPY((S),(data->data + data->ptr), sizeof(S[0])*(L)); \ + data->ptr+=sizeof(S[0])*(L); \ + }while(0) + +#define getdata(X) do { \ + long length; \ + decode_entry(T_STRING, length,data); \ + if(data->ptr + length > data->len || length <0) \ + error("Failed to decode string. (string range error)\n"); \ + X=make_shared_binary_string((char *)(data->data + data->ptr), length); \ + data->ptr+=length; \ + }while(0) + +#define decode_number(X,data) do { \ + int what, e, num; \ + DECODE(); \ + X=(what & T_MASK) | (num<<4); \ + }while(0) \ + + +static void low_decode_type(struct decode_data *data) +{ + int tmp; +one_more_type: + push_type(tmp=GETC()); + switch(tmp) + { + default: + fatal("error in type string.\n"); + /*NOTREACHED*/ + break; + + case T_ASSIGN: + push_type(GETC()); + goto one_more_type; + + case T_FUNCTION: + while(GETC()!=T_MANY) + { + data->ptr--; + low_decode_type(data); + } + push_type(T_MANY); + + case T_MAPPING: + case T_OR: + case T_AND: + low_decode_type(data); + + case T_ARRAY: + case T_MULTISET: + case T_NOT: + goto one_more_type; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case T_INT: + case T_FLOAT: + case T_STRING: + case T_PROGRAM: + case T_MIXED: + case T_VOID: + case T_UNKNOWN: + break; + + case T_OBJECT: + { + INT32 x; + push_type(GETC()); + decode_value2(data); + type_stack_mark(); + switch(sp[-1].type) + { + case T_INT: + push_type_int(0); + break; + + case T_PROGRAM: + push_type_int(sp[-1].u.program->id); + break; + + default: + error("Failed to decode type.\n"); + } + pop_stack(); + type_stack_reverse(); + } + } +} + +/* This really needs to disable threads.... */ +#define decode_type(X,data) do { \ + type_stack_mark(); \ + type_stack_mark(); \ + low_decode_type(data); \ + type_stack_reverse(); \ + (X)=pop_unfinished_type(); \ +} while(0) static void decode_value2(struct decode_data *data) @@ -488,7 +791,14 @@ static void decode_value2(struct decode_data *data) switch(num) { case 0: - APPLY_MASTER("objectof", 1); + if(data->codec) + { + apply(data->codec,"objectof", 1); + }else{ + ref_push_mapping(get_builtin_constants()); + stack_swap(); + f_index(2); + } break; case 1: @@ -502,15 +812,21 @@ static void decode_value2(struct decode_data *data) mapping_insert(data->decoded, &tmp, sp-1); push_svalue(sp-1); decode_value2(data); - APPLY_MASTER("decode_object",2); + if(!data->codec) + error("Failed to decode (no codec)\n"); + apply(data->codec,"decode_object",2); pop_stack(); } + if(data->pickyness && sp[-1].type != T_OBJECT) + error("Failed to decode object.\n"); return; default: error("Object coding not compatible.\n"); break; } + if(data->pickyness && sp[-1].type != T_OBJECT) + error("Failed to decode.\n"); break; case T_FUNCTION: @@ -521,7 +837,14 @@ static void decode_value2(struct decode_data *data) switch(num) { case 0: - APPLY_MASTER("objectof", 1); + if(data->codec) + { + apply(data->codec,"functionof", 1); + }else{ + ref_push_mapping(get_builtin_constants()); + stack_swap(); + f_index(2); + } break; case 1: @@ -533,14 +856,201 @@ static void decode_value2(struct decode_data *data) error("Function coding not compatible.\n"); break; } + if(data->pickyness && sp[-1].type != T_FUNCTION) + error("Failed to decode function.\n"); break; case T_PROGRAM: - tmp=data->counter; - data->counter.u.integer++; - decode_value2(data); - APPLY_MASTER("programof", 1); + switch(num) + { + case 0: + tmp=data->counter; + data->counter.u.integer++; + decode_value2(data); + if(data->codec) + { + apply(data->codec,"programof", 1); + }else{ + ref_push_mapping(get_builtin_constants()); + stack_swap(); + f_index(2); + } + if(data->pickyness && sp[-1].type != T_PROGRAM) + error("Failed to decode program.\n"); + break; + + case 1: + { + int d; + SIZE_T size=0; + char *dat; + struct program *p; + + p=low_allocate_program(); + debug_malloc_touch(p); + tmp.type=T_PROGRAM; + tmp.u.program=p; + mapping_insert(data->decoded, & data->counter, &tmp); + data->counter.u.integer++; + p->refs--; + + decode_number(p->flags,data); + p->flags &= ~(PROGRAM_FINISHED | PROGRAM_OPTIMIZED); + decode_number(p->storage_needed,data); + decode_number(p->timestamp.tv_sec,data); + decode_number(p->timestamp.tv_usec,data); + +#define FOO(X,Y,Z) \ + decode_number( p->num_##Z, data); +#include "program_areas.h" + +#define FOO(NUMTYPE,TYPE,NAME) \ + size=DO_ALIGN(size, ALIGNOF(TYPE)); \ + size+=p->PIKE_CONCAT(num_,NAME)*sizeof(p->NAME[0]); +#include "program_areas.h" + + dat=xalloc(size); + debug_malloc_touch(dat); + MEMSET(dat,0,size); + size=0; +#define FOO(NUMTYPE,TYPE,NAME) \ + size=DO_ALIGN(size, ALIGNOF(TYPE)); \ + p->NAME=(TYPE *)(dat+size); \ + size+=p->PIKE_CONCAT(num_,NAME)*sizeof(p->NAME[0]); +#include "program_areas.h" + + for(e=0;e<p->num_constants;e++) + p->constants[e].type=T_INT; + + debug_malloc_touch(dat); + + p->total_size=size + sizeof(struct program); + + p->flags |= PROGRAM_OPTIMIZED; + + getdata2(p->program, p->num_program); + getdata2(p->linenumbers, p->num_linenumbers); + + for(d=0;d<p->num_identifier_index;d++) + { + decode_number(p->identifier_index[d],data); + if(p->identifier_index[d] > p->num_identifier_references) + { + p->identifier_index[d]=0; + error("Malformed program in decode.\n"); + } + } + + for(d=0;d<p->num_variable_index;d++) + { + decode_number(p->variable_index[d],data); + if(p->variable_index[d] > p->num_identifiers) + { + p->variable_index[d]=0; + error("Malformed program in decode.\n"); + } + } + + for(d=0;d<p->num_identifier_references;d++) + { + decode_number(p->identifier_references[d].inherit_offset,data); + if(p->identifier_references[d].inherit_offset > p->num_inherits) + { + p->identifier_references[d].inherit_offset=0; + error("Malformed program in decode.\n"); + } + decode_number(p->identifier_references[d].identifier_offset,data); + decode_number(p->identifier_references[d].id_flags,data); + } + + for(d=0;d<p->num_strings;d++) + getdata(p->strings[d]); + + debug_malloc_touch(dat); + + data->pickyness++; + p->inherits[0].prog=p; + p->inherits[0].parent_offset=1; + + for(d=1;d<p->num_inherits;d++) + { + decode_number(p->inherits[d].inherit_level,data); + decode_number(p->inherits[d].identifier_level,data); + decode_number(p->inherits[d].parent_offset,data); + decode_number(p->inherits[d].storage_offset,data); + + decode_value2(data); + switch(sp[-1].type) + { + case T_FUNCTION: + if(sp[-1].subtype == FUNCTION_BUILTIN) + error("Failed to decode parent.\n"); + + p->inherits[d].parent_identifier=sp[-1].subtype; + p->inherits[d].prog=program_from_svalue(sp-1); + if(!p->inherits[d].prog) + error("Failed to decode parent.\n"); + add_ref(p->inherits[d].prog); + p->inherits[d].parent=sp[-1].u.object; + sp--; + break; + + case T_PROGRAM: + p->inherits[d].parent_identifier=0; + p->inherits[d].prog=sp[-1].u.program; + sp--; + break; + default: + error("Failed to decode inheritance.\n"); + } + + getdata(p->inherits[d].name); + } + + debug_malloc_touch(dat); + + for(d=0;d<p->num_identifiers;d++) + { + getdata(p->identifiers[d].name); + decode_type(p->identifiers[d].type,data); + decode_number(p->identifiers[d].identifier_flags,data); + decode_number(p->identifiers[d].run_time_type,data); + decode_number(p->identifiers[d].func.offset,data); + } + + debug_malloc_touch(dat); + + for(d=0;d<p->num_constants;d++) + { + decode_value2(data); + p->constants[d]=*--sp; + } + data->pickyness--; + + debug_malloc_touch(dat); + + for(d=0;d<NUM_LFUNS;d++) + decode_number(p->lfuns[d],data); + + debug_malloc_touch(dat); + + { + struct program *new_program_save=new_program; + new_program=p; + fsort((void *)p->identifier_index, + p->num_identifier_index, + sizeof(unsigned short),(fsortfun)program_function_index_compare); + new_program=new_program_save; + } + p->flags |= PROGRAM_FINISHED; + ref_push_program(p); + return; + } + + default: + error("Cannot decode program encoding type %d\n",num); + } break; default: @@ -556,7 +1066,8 @@ static void free_decode_data(struct decode_data *data) free_mapping(data->decoded); } -static INT32 my_decode(struct pike_string *tmp) +static INT32 my_decode(struct pike_string *tmp, + struct object *codec) { ONERROR err; struct decode_data d, *data; @@ -566,6 +1077,8 @@ static INT32 my_decode(struct pike_string *tmp) data->data=(unsigned char *)tmp->str; data->len=tmp->len; data->ptr=0; + data->codec=codec; + data->pickyness=0; if(data->len < 5) return 0; if(GETC() != 182 || @@ -689,12 +1202,25 @@ static void rec_restore_value(char **v, INT32 *l) void f_decode_value(INT32 args) { struct pike_string *s; + struct object *codec; - if(args != 1 || (sp[-1].type != T_STRING)) - error("Illegal argument to decode_value()\n"); + check_all_args("decode_value",args, BIT_STRING, BIT_VOID | BIT_OBJECT | BIT_INT, 0); - s = sp[-1].u.string; - if(!my_decode(s)) + s = sp[-args].u.string; + if(args<2) + { + codec=get_master(); + } + else if(sp[1-args].type == T_OBJECT) + { + codec=sp[1-args].u.object; + } + else + { + codec=0; + } + + if(!my_decode(s, codec)) { char *v=s->str; INT32 l=s->len; @@ -704,3 +1230,4 @@ void f_decode_value(INT32 args) pop_n_elems(args); } + diff --git a/src/gc.c b/src/gc.c index b9e327feaaac7f23376f41815ebd34ce07a8b241..c2fcd938454433bca982577a4c50770f20f3c314 100644 --- a/src/gc.c +++ b/src/gc.c @@ -25,7 +25,7 @@ struct callback *gc_evaluator_callback=0; #include "main.h" #include <math.h> -RCSID("$Id: gc.c,v 1.35 1998/04/20 18:53:16 grubba Exp $"); +RCSID("$Id: gc.c,v 1.36 1998/04/24 00:32:08 hubbe Exp $"); /* Run garbage collect approximate every time we have * 20 percent of all arrays, objects and programs is @@ -337,7 +337,7 @@ void describe_something(void *a, int t, int dm) INT32 line,pos; fprintf(stderr,"**Program id: %ld\n",(long)(p->id)); - if(!p->num_linenumbers) + if(p->flags & PROGRAM_HAS_C_METHODS) { int e; fprintf(stderr,"**The program was written in C.\n"); diff --git a/src/object.c b/src/object.c index 982cc346a3d021d9e38b224383b85b0504d5a8b2..dfe941db334d97c60f22cc9e633bf8f89fe99199 100644 --- a/src/object.c +++ b/src/object.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: object.c,v 1.47 1998/04/17 16:55:48 hubbe Exp $"); +RCSID("$Id: object.c,v 1.48 1998/04/24 00:32:09 hubbe Exp $"); #include "object.h" #include "dynamic_buffer.h" #include "interpret.h" @@ -59,7 +59,7 @@ struct object *low_clone(struct program *p) return o; } -static void call_c_initializers(struct object *o) +void call_c_initializers(struct object *o) { int e; struct frame frame; @@ -77,17 +77,15 @@ static void call_c_initializers(struct object *o) /* clear globals and call C initializers */ for(e=p->num_inherits-1; e>=0; e--) { - int d; + int q; frame.context=p->inherits[e]; add_ref(frame.context.prog); frame.current_storage=o->storage+frame.context.storage_offset; - for(d=0;d<(int)frame.context.prog->num_identifiers;d++) + for(q=0;q<(int)frame.context.prog->num_variable_index;q++) { - if(!IDENTIFIER_IS_VARIABLE(frame.context.prog->identifiers[d].identifier_flags)) - continue; - + int d=frame.context.prog->variable_index[q]; if(frame.context.prog->identifiers[d].run_time_type == T_MIXED) { struct svalue *s; @@ -162,6 +160,23 @@ struct object *parent_clone_object(struct program *p, return o; } +static struct pike_string *low_read_file(char *file) +{ + struct pike_string *s; + INT32 len; + FILE *f=fopen(file,"r"); + if(f) + { + fseek(f,0,SEEK_END); + len=ftell(f); + fseek(f,0,SEEK_SET); + s=begin_shared_string(len); + fread(s->str,1,len,f); + fclose(f); + return end_shared_string(s); + } + return 0; +} struct object *get_master(void) { @@ -184,24 +199,43 @@ struct object *get_master(void) if(!master_program) { - INT32 len; - struct pike_string *s; + extern struct timeval TM; + struct pike_string *s,*s2; + char *tmp=xalloc(strlen(master_file)+3); + MEMCPY(tmp, master_file, strlen(master_file)+1); + strcat(tmp,".o"); + s=low_read_file(tmp); + free(tmp); + if(s) + { + JMP_BUF tmp; + if(SETJMP(tmp)) + { + /* do nothing */ + UNSETJMP(tmp); + }else{ + extern f_decode_value(INT32); + + push_string(s); + push_int(0); + f_decode_value(2); + if(sp[-1].type == T_PROGRAM) + goto compiled; - FILE *f=fopen(master_file,"r"); - if(f) + pop_stack(); + + } + } + s2=low_read_file(master_file); + if(s2) { - fseek(f,0,SEEK_END); - len=ftell(f); - fseek(f,0,SEEK_SET); - s=begin_shared_string(len); - fread(s->str,1,len,f); - fclose(f); - push_string(end_shared_string(s)); + push_string(s2); push_text(master_file); f_cpp(2); f_compile(1); - + + compiled: if(sp[-1].type != T_PROGRAM) { pop_stack(); @@ -284,7 +318,7 @@ void destruct(struct object *o) /* free globals and call C de-initializers */ for(e=p->num_inherits-1; e>=0; e--) { - int d; + int q; frame.context=p->inherits[e]; add_ref(frame.context.prog); @@ -293,10 +327,9 @@ void destruct(struct object *o) if(frame.context.prog->exit) frame.context.prog->exit(o); - for(d=0;d<(int)frame.context.prog->num_identifiers;d++) + for(q=0;q<(int)frame.context.prog->num_variable_index;q++) { - if(!IDENTIFIER_IS_VARIABLE(frame.context.prog->identifiers[d].identifier_flags)) - continue; + int d=frame.context.prog->variable_index[q]; if(frame.context.prog->identifiers[d].run_time_type == T_MIXED) { @@ -931,7 +964,7 @@ void gc_mark_object_as_referenced(struct object *o) for(e=p->num_inherits-1; e>=0; e--) { - int d; + int q; frame.context=p->inherits[e]; add_ref(frame.context.prog); @@ -940,10 +973,9 @@ void gc_mark_object_as_referenced(struct object *o) if(frame.context.prog->gc_marked) frame.context.prog->gc_marked(o); - for(d=0;d<(int)frame.context.prog->num_identifiers;d++) + for(q=0;q<(int)frame.context.prog->num_variable_index;q++) { - if(!IDENTIFIER_IS_VARIABLE(frame.context.prog->identifiers[d].identifier_flags)) - continue; + int d=frame.context.prog->variable_index[q]; if(frame.context.prog->identifiers[d].run_time_type == T_MIXED) { @@ -996,7 +1028,7 @@ void gc_check_all_objects(void) for(e=p->num_inherits-1; e>=0; e--) { - int d; + int q; frame.context=p->inherits[e]; add_ref(frame.context.prog); @@ -1004,11 +1036,10 @@ void gc_check_all_objects(void) if(frame.context.prog->gc_check) frame.context.prog->gc_check(o); - - for(d=0;d<(int)frame.context.prog->num_identifiers;d++) + + for(q=0;q<(int)frame.context.prog->num_variable_index;q++) { - if(!IDENTIFIER_IS_VARIABLE(frame.context.prog->identifiers[d].identifier_flags)) - continue; + int d=frame.context.prog->variable_index[q]; if(frame.context.prog->identifiers[d].run_time_type == T_MIXED) { diff --git a/src/object.h b/src/object.h index e9ab0ccce1303a4ba3d9900df9823a8f2e474e28..e21c0ee3938ee0f933b816a27beea8cbac693950 100644 --- a/src/object.h +++ b/src/object.h @@ -5,7 +5,7 @@ \*/ /* - * $Id: object.h,v 1.18 1998/04/20 18:53:20 grubba Exp $ + * $Id: object.h,v 1.19 1998/04/24 00:32:09 hubbe Exp $ */ #ifndef OBJECT_H #define OBJECT_H @@ -42,8 +42,9 @@ extern struct program *master_program; #define this_object() (add_ref(fp->current_object), fp->current_object) /* Prototypes begin here */ -void setup_fake_object(void); struct object *low_clone(struct program *p); +void call_c_initializers(struct object *o); +void do_free_object(struct object *o); struct object *debug_clone_object(struct program *p, int args); struct object *parent_clone_object(struct program *p, struct object *parent, diff --git a/src/program.c b/src/program.c index 12f6a75cd128b742540ba077efc1b99884d8697d..94251ef89f7dfb910bd64be567381201f70651e9 100644 --- a/src/program.c +++ b/src/program.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: program.c,v 1.86 1998/04/19 03:14:15 per Exp $"); +RCSID("$Id: program.c,v 1.87 1998/04/24 00:32:09 hubbe Exp $"); #include "program.h" #include "object.h" #include "dynamic_buffer.h" @@ -26,6 +26,8 @@ RCSID("$Id: program.c,v 1.86 1998/04/19 03:14:15 per Exp $"); #include "operators.h" #include "builtin_functions.h" #include "stuff.h" +#include "mapping.h" +#include "cyclic.h" #include <errno.h> #include <fcntl.h> @@ -105,6 +107,9 @@ static INT32 last_line = 0; static INT32 last_pc = 0; static struct pike_string *last_file = 0; dynamic_buffer used_modules; +INT32 num_used_modules; +static struct mapping *resolve_cache=0; +static struct mapping *module_index_cache=0; /* So what if we don't have templates? / Hubbe */ @@ -174,25 +179,60 @@ void use_module(struct svalue *s) { if( (1<<s->type) & (BIT_MAPPING | BIT_OBJECT)) { + num_used_modules++; assign_svalue_no_free((struct svalue *) low_make_buf_space(sizeof(struct svalue), &used_modules), s); + if(module_index_cache) + { + free_mapping(module_index_cache); + module_index_cache=0; + } }else{ yyerror("Module is neither mapping nor object"); } } - +void unuse_modules(INT32 howmany) +{ + if(!howmany) return; +#ifdef DEBUG + if(howmany *sizeof(struct svalue) > used_modules.s.len) + fatal("Unusing too many modules.\n"); +#endif + num_used_modules-=howmany; + low_make_buf_space(-sizeof(struct svalue)*howmany, &used_modules); + free_svalues((struct svalue *)low_make_buf_space(0, &used_modules), + howmany, + BIT_MAPPING | BIT_OBJECT); + if(module_index_cache) + { + free_mapping(module_index_cache); + module_index_cache=0; + } +} int low_find_shared_string_identifier(struct pike_string *name, struct program *prog); -struct node_s *find_module_identifier(struct pike_string *ident) +static struct node_s *index_modules(struct pike_string *ident) { + struct node_s *ret; JMP_BUF tmp; - node *ret; + + if(module_index_cache) + { + struct svalue *tmp=low_mapping_string_lookup(module_index_cache,ident); + if(tmp) + { + if(!(IS_ZERO(tmp) && tmp->subtype==1)) + return mksvaluenode(tmp); + return 0; + } + } + if(SETJMP(tmp)) { @@ -215,8 +255,10 @@ struct node_s *find_module_identifier(struct pike_string *ident) if(!IS_UNDEFINED(sp-1)) { -/* fprintf(stderr,"MOD: %s, %d %d\n",ident->str, current_line, sp[-1].type); */ UNSETJMP(tmp); + if(!module_index_cache) + module_index_cache=allocate_mapping(10); + mapping_string_insert(module_index_cache, ident, sp-1); ret=mksvaluenode(sp-1); pop_stack(); return ret; @@ -226,6 +268,16 @@ struct node_s *find_module_identifier(struct pike_string *ident) } UNSETJMP(tmp); + return 0; +} + +struct node_s *find_module_identifier(struct pike_string *ident) +{ + struct node_s *ret; + + if((ret=index_modules(ident))) return ret; + + { struct program_state *p=previous_program_state; int n; @@ -236,23 +288,61 @@ struct node_s *find_module_identifier(struct pike_string *ident) { struct identifier *id; id=ID_FROM_INT(p->new_program, i); -#if 0 - if(IDENTIFIER_IS_CONSTANT(id->identifier_flags)) + return mkexternalnode(n, i, id); + } + } + } + + + if(resolve_cache) + { + struct svalue *tmp=low_mapping_string_lookup(resolve_cache,ident); + if(tmp) + { + if(!(IS_ZERO(tmp) && tmp->subtype==1)) + return mkconstantsvaluenode(tmp); + + return 0; + } + } + + if(!num_parse_error && get_master()) + { + DECLARE_CYCLIC(); + node *ret=0; + if(BEGIN_CYCLIC(ident, lex.current_file)) + { + my_yyerror("Recursive module dependency in %s.", + ident->str); + }else{ + SET_CYCLIC_RET(1); + + ref_push_string(ident); + ref_push_string(lex.current_file); + SAFE_APPLY_MASTER("resolv", 2); + + if(throw_value.type == T_STRING) + { + if(compiler_pass==2) + my_yyerror("%s",throw_value.u.string->str); + } + else + { + if(!resolve_cache) + resolve_cache=allocate_mapping(10); + mapping_string_insert(resolve_cache,ident,sp-1); + + if(!(IS_ZERO(sp-1) && sp[-1].subtype==1)) { - struct svalue *s=PROG_FROM_INT(p->new_program, i)->constants+ - id->func.offset; - if(s->type != T_PROGRAM) - { - ret=mksvaluenode(s); - return ret; - } + ret=mkconstantsvaluenode(sp-1); } -#endif - - return mkexternalnode(n, i, id); } + pop_stack(); + END_CYCLIC(); } + if(ret) return ret; } + return 0; } @@ -336,7 +426,7 @@ void optimize_program(struct program *p) } /* internal function to make the index-table */ -static int funcmp(const void *a,const void *b) +int program_function_index_compare(const void *a,const void *b) { return my_order_strcmp(ID_FROM_INT(new_program, *(unsigned short *)a)->name, @@ -383,7 +473,7 @@ void fixate_program(void) } fsort((void *)new_program->identifier_index, new_program->num_identifier_index, - sizeof(unsigned short),(fsortfun)funcmp); + sizeof(unsigned short),(fsortfun)program_function_index_compare); for(i=0;i<NUM_LFUNS;i++) @@ -392,6 +482,22 @@ void fixate_program(void) new_program->flags |= PROGRAM_FIXED; } +struct program *low_allocate_program(void) +{ + struct program *p; + p=ALLOC_STRUCT(program); + MEMSET(p, 0, sizeof(struct program)); + + GC_ALLOC(); + p->refs=1; + p->id=++current_program_id; + + if((p->next=first_program)) first_program->prev=p; + first_program=p; + GETTIMEOFDAY(& p->timestamp); + return p; +} + /* * Start building a new program */ @@ -408,14 +514,7 @@ void low_start_new_program(struct program *p, if(!p) { - p=ALLOC_STRUCT(program); - MEMSET(p, 0, sizeof(struct program)); - - p->refs=1; - p->id=++current_program_id; - - if((p->next=first_program)) first_program->prev=p; - first_program=p; + p=low_allocate_program(); }else{ add_ref(p); } @@ -431,9 +530,9 @@ void low_start_new_program(struct program *p, #define PUSH #include "compilation.h" + num_used_modules=0; init_type_stack(); - low_reinit_buf(& used_modules); if(p && (p->flags & PROGRAM_FINISHED)) { @@ -494,20 +593,13 @@ void low_start_new_program(struct program *p, add_to_inherits(i); } - { - struct svalue tmp; - tmp.type=T_MAPPING; -#ifdef __CHECKER__ - tmp.subtype=0; -#endif /* __CHECKER__ */ - tmp.u.mapping=get_builtin_constants(); - use_module(& tmp); - } init_node=0; num_parse_error=0; push_compiler_frame(); + if(lex.current_file) + store_linenumber(lex.current_line, lex.current_file); } void start_new_program(void) @@ -524,52 +616,61 @@ void really_free_program(struct program *p) if(id_to_program_cache[p->id & (ID_TO_PROGRAM_CACHE_SIZE-1)]==p) id_to_program_cache[p->id & (ID_TO_PROGRAM_CACHE_SIZE-1)]=0; - for(e=0; e<p->num_strings; e++) - free_string(p->strings[e]); + if(p->strings) + for(e=0; e<p->num_strings; e++) + if(p->strings[e]) + free_string(p->strings[e]); - for(e=0; e<p->num_identifiers; e++) + if(p->identifiers) { - free_string(p->identifiers[e].name); - free_string(p->identifiers[e].type); + for(e=0; e<p->num_identifiers; e++) + { + if(p->identifiers[e].name) + free_string(p->identifiers[e].name); + if(p->identifiers[e].type) + free_string(p->identifiers[e].type); + } } - for(e=0; e<p->num_constants; e++) - free_svalue(p->constants+e); + if(p->constants) + free_svalues(p->constants, p->num_constants, BIT_MIXED); - for(e=0; e<p->num_inherits; e++) - { - if(p->inherits[e].name) - free_string(p->inherits[e].name); - if(e) + if(p->inherits) + for(e=0; e<p->num_inherits; e++) { - free_program(p->inherits[e].prog); + if(p->inherits[e].name) + free_string(p->inherits[e].name); + if(e) + { + if(p->inherits[e].prog) + free_program(p->inherits[e].prog); + } + if(p->inherits[e].parent) + free_object(p->inherits[e].parent); } - if(p->inherits[e].parent) - free_object(p->inherits[e].parent); - } if(p->prev) p->prev->next=p->next; else first_program=p->next; - + if(p->next) p->next->prev=p->prev; - + if(p->flags & PROGRAM_OPTIMIZED) - { - if(p->program) - free(p->program); + { + if(p->program) + free(p->program); #define FOO(NUMTYPE,TYPE,NAME) p->NAME=0; #include "program_areas.h" - }else{ + }else{ #define FOO(NUMTYPE,TYPE,NAME) \ - if(p->NAME) { free((char *)p->NAME); p->NAME=0; } + if(p->NAME) { free((char *)p->NAME); p->NAME=0; } #include "program_areas.h" - } - + } + free((char *)p); - + GC_FREE(); } @@ -625,6 +726,12 @@ static void toss_compilation_resources(void) free((char *)malloc_size_program); malloc_size_program=0; } + + if(module_index_cache) + { + free_mapping(module_index_cache); + module_index_cache=0; + } while(compiler_frame) pop_compiler_frame(); @@ -634,17 +741,8 @@ static void toss_compilation_resources(void) free_string(last_file); last_file=0; } - - { - struct svalue *modules=(struct svalue *)used_modules.s.str; - INT32 e; - for(e=0;e<(long)(used_modules.s.len / sizeof(struct svalue));e++) - free_svalue(modules+e); - - toss_buffer(&used_modules); - } - + unuse_modules(num_used_modules); } int sizeof_variable(int run_time_type) @@ -836,20 +934,25 @@ struct program *end_first_pass(int finish) new_program->flags |= PROGRAM_FINISHED; } - GC_ALLOC(); } toss_compilation_resources(); #define POP #include "compilation.h" + compilation_depth--; - threads_disabled--; - co_signal(&threads_disabled_change); + if(!--threads_disabled) + co_signal(&threads_disabled_change); /* fprintf(stderr, "end_first_pass(): compilation_depth:%d\n", compilation_depth); */ free_all_nodes(); + if(!compiler_frame && compiler_pass==2 && resolve_cache) + { + free_mapping(resolve_cache); + resolve_cache=0; + } return prog; } @@ -1308,12 +1411,14 @@ int low_define_variable(struct pike_string *name, ref.id_flags=flags; ref.identifier_offset=new_program->num_identifiers; ref.inherit_offset=0; + + add_to_variable_index(ref.identifier_offset); add_to_identifiers(dummy); n=new_program->num_identifier_references; add_to_identifier_references(ref); - + return n; } @@ -1676,6 +1781,8 @@ INT32 define_function(struct pike_string *name, fun.run_time_type=T_FUNCTION; fun.identifier_flags=function_flags; + if(function_flags & IDENTIFIER_C_FUNCTION) + new_program->flags |= PROGRAM_HAS_C_METHODS; if(func) fun.func = *func; @@ -1704,6 +1811,8 @@ INT32 define_function(struct pike_string *name, copy_shared_string(fun.type, type); fun.identifier_flags=function_flags; + if(function_flags & IDENTIFIER_C_FUNCTION) + new_program->flags |= PROGRAM_HAS_C_METHODS; fun.run_time_type=T_FUNCTION; @@ -2019,6 +2128,8 @@ struct program *compile(struct pike_string *prog) struct lex save_lex; int save_depth=compilation_depth; int saved_threads_disabled = threads_disabled; + dynamic_buffer used_modules_save = used_modules; + INT32 num_used_modules_save = num_used_modules; void yyparse(void); #ifdef DEBUG @@ -2026,6 +2137,18 @@ struct program *compile(struct pike_string *prog) fatal("Compiler exited with longjump!\n"); #endif + num_used_modules=0; + initialize_buf(&used_modules); + { + struct svalue tmp; + tmp.type=T_MAPPING; +#ifdef __CHECKER__ + tmp.subtype=0; +#endif /* __CHECKER__ */ + tmp.u.mapping=get_builtin_constants(); + use_module(& tmp); + } + save_lex=lex; lex.end=prog->str+prog->len; @@ -2064,12 +2187,22 @@ struct program *compile(struct pike_string *prog) #endif /* DEBUG */ threads_disabled = saved_threads_disabled; /* fprintf(stderr, "compile() Leave: threads_disabled:%d, compilation_depth:%d\n", threads_disabled, compilation_depth); */ - co_signal(&threads_disabled_change); + if(!threads_disabled) + co_signal(&threads_disabled_change); free_string(lex.current_file); lex=save_lex; + unuse_modules(1); +#ifdef DEBUG + if(num_used_modules) + fatal("Failed to pop modules properly.\n"); +#endif + + toss_buffer(&used_modules); compilation_depth=save_depth; + used_modules = used_modules_save; + num_used_modules = num_used_modules_save ; #ifdef DEBUG UNSETJMP(tmp); @@ -2149,7 +2282,11 @@ void cleanup_program(void) } } #endif - + if(resolve_cache) + { + free_mapping(resolve_cache); + resolve_cache=0; + } } #ifdef GC2 @@ -2508,3 +2645,42 @@ int implements(struct program *a, struct program *b) implements_cache[hval].ret=low_implements(a,b); return implements_cache[hval].ret; } + +#if 0 +void f_encode_program(INT32 args) +{ + check_stack(20); + f_version(); + push_int(p->flags); + push_int(p->storage_needed); + if(p->init || p->exit || p->gc_marked || p->gc_check) + error("Cannot encode C programs.\n"); + push_int(total_size); + push_string(make_shared_binary_string(p->program, p->num_program)); + push_string(make_shared_binary_string(p->linenumbers, p->num_linenumbers)); + push_string(make_shared_binary_string((char *)p->identifier_index, p->num_identifier_index * sizeof(unsigned short*))); + push_string(make_shared_binary_string((char *)p->variable_index, p->num_variable_index * sizeof(unsigned short*))); + push_string(make_shared_binary_string((char *)p->identifier_references, p->num_identifier_references * sizeof(struct reference))); + check_stack(p->num_strings); + for(e=0;e<p->num_strings;e++) ref_push_string(p->strings[e]); + f_aggregate(p->num_strings); + + check_stack(p->num_inherits * 2); + for(e=1;e<p->num_strings;e++) + { + ref_push_string(p->inherits[e].name); + } + + f_aggregate(p->num_inherits); + + check_stack(NUM_LFUNS); + for(e=0;e<NUM_LFUNS;e++) push_int(p->lfuns[e]); + + UNSET_ONERROR(tmp); + + free_mapping(data->encoded); + pop_n_elems(args); + push_string(low_free_buf(&data->buf)); +} + +#endif diff --git a/src/program.h b/src/program.h index b28c2c61cd900b259732851160e39ff57fe43481..ca7afc91d5c8e7b1b387bbad2de39f66d57ecd7c 100644 --- a/src/program.h +++ b/src/program.h @@ -5,7 +5,7 @@ \*/ /* - * $Id: program.h,v 1.40 1998/04/14 22:10:50 hubbe Exp $ + * $Id: program.h,v 1.41 1998/04/24 00:32:09 hubbe Exp $ */ #ifndef PROGRAM_H #define PROGRAM_H @@ -14,6 +14,7 @@ #include "global.h" #include "pike_types.h" #include "svalue.h" +#include "time_stuff.h" #define LFUN___INIT 0 #define LFUN_CREATE 1 @@ -180,12 +181,15 @@ struct inherit /* Program will be destructed as soon at it runs out of references. */ #define PROGRAM_DESTRUCT_IMMEDIATE 16 +#define PROGRAM_HAS_C_METHODS 32 + struct program { INT32 refs; INT32 id; /* used to identify program in caches */ INT32 flags; INT32 storage_needed; /* storage needed in the object struct */ + struct timeval timestamp; struct program *next; struct program *prev; @@ -230,6 +234,7 @@ extern struct program *first_program; extern int compiler_pass; extern long local_class_counter; extern int catch_level; +extern INT32 num_used_modules; #define COMPILER_IN_CATCH 1 @@ -240,11 +245,14 @@ extern int catch_level; void ins_int(INT32 i, void (*func)(char tmp)); void ins_short(INT16 i, void (*func)(char tmp)); void use_module(struct svalue *s); +void unuse_modules(INT32 howmany); struct node_s *find_module_identifier(struct pike_string *ident); struct program *parent_compilation(int level); struct program *id_to_program(INT32 id); void optimize_program(struct program *p); +int program_function_index_compare(const void *a,const void *b); void fixate_program(void); +struct program *low_allocate_program(void); void low_start_new_program(struct program *p, struct pike_string *name, int flags); @@ -362,6 +370,7 @@ int find_child(struct program *parent, struct program *child); void yywarning(char *fmt, ...) ATTRIBUTE((format(printf,1,2))); struct implements_cache_s; int implements(struct program *a, struct program *b); +void f_encode_program(INT32 args); /* Prototypes end here */ diff --git a/src/program_areas.h b/src/program_areas.h index e10c5dfafc16783d8e00e76addf1aa1c17bba4da..0cb01707e9d4ea512e88f88f4205df7a5987fb65 100644 --- a/src/program_areas.h +++ b/src/program_areas.h @@ -1,15 +1,15 @@ -/* $Id: program_areas.h,v 1.4 1998/04/08 01:00:58 hubbe Exp $ */ +/* $Id: program_areas.h,v 1.5 1998/04/24 00:32:10 hubbe Exp $ */ /* Who needs templates anyway? / Hubbe */ /* Program *must* be first! */ FOO(SIZE_T,unsigned char,program) FOO(SIZE_T,char,linenumbers) FOO(unsigned INT16,unsigned INT16,identifier_index) +FOO(unsigned INT16,unsigned INT16,variable_index) FOO(unsigned INT16,struct reference,identifier_references) FOO(unsigned INT16,struct pike_string *,strings) FOO(unsigned INT16,struct inherit,inherits) FOO(unsigned INT16,struct identifier,identifiers) FOO(unsigned INT16,struct svalue, constants) - #undef FOO