diff --git a/lib/master.pike.in b/lib/master.pike.in index 7b8ddea6d59f0491c61b6bfbb2015a3ff9b416b7..2e6bbaaed8c7246e9c73d0dbf4b93c2fcc2ecd46 100644 --- a/lib/master.pike.in +++ b/lib/master.pike.in @@ -1,6 +1,6 @@ /* -*- Pike -*- * - * $Id: master.pike.in,v 1.169 2001/09/02 01:36:13 marcus Exp $ + * $Id: master.pike.in,v 1.170 2001/10/05 01:30:11 hubbe Exp $ * * Master-file for Pike. * @@ -477,7 +477,7 @@ static program low_findprog(string pname, AUTORELOAD_CHECK_FILE(oname); return programs[fname] = decode_value(master_read_file(oname), - Codec()); + Codec(fname,mkobj)); }; if (handler) { handler->compile_warning(oname, 0, @@ -532,6 +532,16 @@ static program low_findprog(string pname, return 0; } +// +// This function is called by the compiler +// when a delayed compilation error occurs +// +void unregister(program p) +{ + if(string fname=search(programs,p)) + m_delete(programs, fname); +} + static program findprog(string pname, string ext, object|void handler, @@ -787,37 +797,78 @@ object cast_to_object(string oname, string current_file) return 0; } -class dirnode(string dirname, object|void handler) +class dirnode { + string dirname; + object|void handler; constant is_resolv_dirnode = 1; mixed module=module_checker(); mapping(string:mixed) cache=([]); array(string) files; + void create(string d, object|void h) + { + dirname=d; + handler=h; + fc[dirname]=this_object(); + if(dirname[sizeof(dirname)-5..]==".pmod") + fc[dirname[..sizeof(dirname)-6]]=this_object(); +#ifdef MODULE_TRACE + werror("%*ndirnode(%O,%O);\n",sizeof(backtrace())-1,dirname,h); +// werror(describe_backtrace( ({"HERE\n",backtrace()}))); +#endif + } + class module_checker { int `!() { - module=0; +#ifdef MODULE_TRACE + werror("%*ndirnode(%O)->module_checker()->`!()\n",sizeof(backtrace()),dirname); +#endif if(module=findmodule(dirname+"/module", handler)) + { if(mixed tmp=module->_module_value) module=tmp; + + /* This allows for `[] to have side effects first time + * it is called. (Specifically, the Calendar module uses + * this + */ + cache=([]); + _cache_full=0; + } return !module; } - mixed `[](string index) { if(module) return module[index]; } + mixed `[](string index) + { +#ifdef MODULE_TRACE + werror("%*ndirnode(%O)->module_checker()[%O]\n",sizeof(backtrace()),dirname,index); +#endif + if(module) return module[index]; + } array(string) _indices() { if(module) return indices(module); } array _values() { if(module) return values(module); } } static mixed ind(string index) { +#ifdef MODULE_TRACE + werror("%*nDirnode(%O) ind[%O] -> ???\n",sizeof(backtrace()),dirname,index); +#endif if(module) { +#ifdef MODULE_TRACE + werror("%*nDirnode(%O) module[%O] -> ???\n",sizeof(backtrace()),dirname,index); +#endif object o; +// _describe(module); if(!zero_type(o=module[index])) { -// werror("Dirnode(%O) module[%O] -> %O\n",dirname,index, o); +#ifdef MODULE_TRACE + werror("%*nDirnode(%O) module[%O] -> %O\n",sizeof(backtrace()),dirname,index, o); +#endif return o; } } @@ -854,16 +905,25 @@ class dirnode(string dirname, object|void handler) mixed `[](string index) { mixed ret; -// werror("Dirnode(%O) cache[%O] ?????\n",dirname,index); - if(!zero_type(ret=cache[index])) +#ifdef MODULE_TRACE + werror("%*nDirnode(%O) cache[%O] ?????\n",sizeof(backtrace()),dirname,index); +#endif + if(!zero_type(ret=cache[index])) { -// werror("Dirnode(%O) cache[%O] -> %O\n",dirname,index, ret); +#ifdef MODULE_TRACE + werror("%*nDirnode(%O) cache[%O] -> %O\n",sizeof(backtrace()),dirname,index, ret); +#endif // The check below is to (hopefully) avoid calling any function // in ret (like `! or `==) in case it's an object. if(!intp (ret) || ret) return ret; return UNDEFINED; } - return cache[index]=ind(index); + ret=ind(index); + + // Kluge! + if(ret == __placeholder_object) return ret; + + return cache[index]=ret; } static int _cache_full; @@ -1026,6 +1086,9 @@ mapping(string:mixed) fc=([]); object findmodule(string fullname, object|void handler) { object o; +#ifdef MODULE_TRACE + werror("%*nfindmodule(%O)\n",sizeof(backtrace()),fullname); +#endif if(!zero_type(o=fc[fullname])) { // werror("fc[%O] -> %O\n",fullname, o); @@ -1035,7 +1098,7 @@ object findmodule(string fullname, object|void handler) if(Stat stat=master_file_stat(fakeroot(fullname+".pmod"))) { if(stat[1]==-2) - return fc[fullname]=dirnode(fullname+".pmod", handler); + return dirnode(fullname+".pmod", handler); } if(o = low_cast_to_object(fullname+".pmod", "/.", handler)) @@ -1062,7 +1125,8 @@ mixed handle_import(string what, string|void current_file, object|void handler) if (handler) { return dirnode(path, handler); } - return fc[path]=dirnode(path); + if(fc[path]) return fc[path]; + return dirnode(path); } @@ -1204,6 +1268,7 @@ class CompatResolver mixed resolv_base(string identifier, string|void current_file, object|void current_handler) { +// werror("Resolv_base(%O)\n",identifier); array(mixed) tmp = ({}); string dir=current_file ? dirname(current_file) : "/"; @@ -1245,6 +1310,8 @@ class CompatResolver mixed resolv(string identifier, string|void current_file, object|void current_handler) { +// werror("Resolv(%O)\n",identifier); + // FIXME: Support having the cache in the handler? if( no_resolv[ identifier ] ) return UNDEFINED; @@ -1257,8 +1324,12 @@ class CompatResolver mixed ret; string id=identifier+":"+(current_file ? dirname(current_file) : "-"); - if( !zero_type (ret = resolv_cache[id]) ) - return ret == ZERO_TYPE ? UNDEFINED : resolv_cache[id]; + if( zero_type (ret = resolv_cache[id]) != 1 ) + { +// werror("Resolv cached(%O) => %O (%d)\n",id,resolv_cache[id],zero_type(resolv_cache[id])); + return ret == ZERO_TYPE ? UNDEFINED : ret; + } + array(string) tmp=identifier/"."; ret=resolv_base(tmp[0], current_file, current_handler); foreach(tmp[1..],string index) ret=ret[index]; @@ -2386,6 +2457,34 @@ string describe_error (mixed trace) class Codec { + string fname; + int mkobj; + program prog_to_mkobj; + void create(void|string f,void|int m) + { + fname=f; + mkobj=m; + } + + void __register_new_program(program p) + { + if(fname) + { + programs[fname]=prog_to_mkobj=p; + fname=0; + } + } + + + void __register_new_object(program p) + { + if(prog_to_mkobj == p) + { + objects[p]=p(); + prog_to_mkobj=0; + } + } + mapping f=all_constants(); string nameof(mixed x) diff --git a/src/builtin_functions.c b/src/builtin_functions.c index e91792034355f3a8d3523237de79fc582e68f6cc..7e7a4016ea46236ad3a25ec0b9c52314daecf50a 100644 --- a/src/builtin_functions.c +++ b/src/builtin_functions.c @@ -5,7 +5,7 @@ \*/ /**/ #include "global.h" -RCSID("$Id: builtin_functions.c,v 1.407 2001/09/27 20:28:28 hubbe Exp $"); +RCSID("$Id: builtin_functions.c,v 1.408 2001/10/05 01:30:11 hubbe Exp $"); #include "interpret.h" #include "svalue.h" #include "pike_macros.h" @@ -1060,17 +1060,18 @@ PMOD_EXPORT void f_zero_type(INT32 args) if(args < 1) SIMPLE_TOO_FEW_ARGS_ERROR("zero_type",1); - if(Pike_sp[-args].type != T_INT) + if((Pike_sp[-args].type==T_OBJECT || Pike_sp[-args].type==T_FUNCTION) + && !Pike_sp[-args].u.object->prog) { pop_n_elems(args); - push_int(0); + push_int(NUMBER_DESTRUCTED); } - else if((Pike_sp[-args].type==T_OBJECT || Pike_sp[-args].type==T_FUNCTION) - && !Pike_sp[-args].u.object->prog) + else if(Pike_sp[-args].type != T_INT) { pop_n_elems(args); - push_int(NUMBER_DESTRUCTED); + push_int(0); } + else { pop_n_elems(args-1); Pike_sp[-1].u.integer=Pike_sp[-1].subtype; @@ -3140,10 +3141,6 @@ PMOD_EXPORT void f_compile(INT32 args) p = compile(Pike_sp[-args].u.string, o, major, minor, p, placeholder); -#ifdef PIKE_DEBUG - if(!(p->flags & PROGRAM_FINISHED)) - fatal("Got unfinished program from internal compile().\n"); -#endif pop_n_elems(args); push_program(p); } diff --git a/src/compilation.h b/src/compilation.h index 52cf7eaeea16557ebf771e8e088cabdd2a88788b..15cda81736be91f0fcfd584f2cca37affffb2048 100644 --- a/src/compilation.h +++ b/src/compilation.h @@ -1,5 +1,5 @@ /* - * $Id: compilation.h,v 1.24 2001/10/02 09:08:18 hubbe Exp $ + * $Id: compilation.h,v 1.25 2001/10/05 01:30:12 hubbe Exp $ * * Compilator state push / pop operator construction file * @@ -149,6 +149,8 @@ IMEMBER(int, compat_major, PIKE_MAJOR_VERSION) IMEMBER(int, compat_minor, PIKE_MINOR_VERSION) ZMEMBER(int, check_final, 0) + ZMEMBER(struct program_state *,depends_on,0) + ZMEMBER(struct compilation *,compiler,0) SEND #undef PCODE diff --git a/src/encode.c b/src/encode.c index fe11e5e308ac0cb97ea0eebf1a1d1b5287d0b420..4bf50c3deea09278050347c876ff42696dba42b7 100644 --- a/src/encode.c +++ b/src/encode.c @@ -25,7 +25,7 @@ #include "version.h" #include "bignum.h" -RCSID("$Id: encode.c,v 1.129 2001/09/24 14:25:54 grubba Exp $"); +RCSID("$Id: encode.c,v 1.130 2001/10/05 01:30:12 hubbe Exp $"); /* #define ENCODE_DEBUG */ @@ -2115,6 +2115,12 @@ static void decode_value2(struct decode_data *data) SET_ONERROR(err3, zap_unfinished_program, p); debug_malloc_touch(p); + if(data->codec) + { + ref_push_program(p); + apply(data->codec, "__register_new_program", 1); + pop_stack(); + } tmp.type=T_PROGRAM; tmp.u.program=p; EDB(2,fprintf(stderr, "%*sDecoding a program to <%d>: ", @@ -2390,6 +2396,13 @@ static void decode_value2(struct decode_data *data) debug_malloc_touch(dat); debug_malloc_touch(p); p->flags |= PROGRAM_PASS_1_DONE | PROGRAM_FIXED; + if(data->codec) + { + ref_push_program(p); + apply(data->codec, "__register_new_object", 1); + pop_stack(); + } + for(d=0;d<p->num_constants;d++) { decode_value2(data); diff --git a/src/global.h b/src/global.h index 744b9200eb92cf6844d4cf5a79600ef1cc8c36f5..90ac0d29ce98e01e3937ed920ce20b68104be07b 100644 --- a/src/global.h +++ b/src/global.h @@ -5,7 +5,7 @@ \*/ /* - * $Id: global.h,v 1.64 2001/08/30 23:09:57 mast Exp $ + * $Id: global.h,v 1.65 2001/10/05 01:30:12 hubbe Exp $ */ #ifndef GLOBAL_H #define GLOBAL_H @@ -232,9 +232,11 @@ void *alloca(); #ifndef WITH_DOUBLE_PRECISION_SVALUE #define FLOAT_TYPE float +#define SIZEOF_FLOAT_TYPE SIZEOF_FLOAT #else #ifdef WITH_LONG_DOUBLE_PRECISION_SVALUE #define FLOAT_TYPE long double +#define SIZEOF_FLOAT_TYPE SIZEOF_LONG_DOUBLE #else #define FLOAT_TYPE double #endif /* long double */ @@ -242,15 +244,19 @@ void *alloca(); #ifdef WITH_LONG_INT #define INT_TYPE long +#define SIZEOF_INT_TYPE SIZEOF_LONG #else #ifdef WITH_LONG_LONG_INT #define INT_TYPE long long +#define SIZEOF_INT_TYPE SIZEOF_LONG_LONG #else #ifdef WITH_SHORT_INT #define INT_TYPE short +#define SIZEOF_INT_TYPE SIZEOF_SHORT #else #ifdef WITH_INT_INT #define INT_TYPE int +#define SIZEOF_INT_TYPE SIZEOF_INT #else #if (SIZEOF_CHAR_P > 4) && 0 /* This isn't a good idea on architectures where @@ -261,6 +267,7 @@ void *alloca(); #define INT_TYPE LONGEST #else /* !(sizeof(char *) > 4) */ #define INT_TYPE INT32 +#define SIZEOF_INT_TYPE 4 #endif /* sizeof(char *) > 4 */ #endif /* WITH_INT_INT */ #endif /* WITH_SHORT_INT */ diff --git a/src/interpret.c b/src/interpret.c index 9e9e13e93d233dbf1b645e573aba97ea03155ed0..27afad4131df75c534dd544e6e7894991dcf1bf6 100644 --- a/src/interpret.c +++ b/src/interpret.c @@ -5,7 +5,7 @@ \*/ /**/ #include "global.h" -RCSID("$Id: interpret.c,v 1.249 2001/09/24 14:14:46 grubba Exp $"); +RCSID("$Id: interpret.c,v 1.250 2001/10/05 01:30:12 hubbe Exp $"); #include "interpret.h" #include "object.h" #include "program.h" @@ -1456,6 +1456,7 @@ PMOD_EXPORT void f_call_function(INT32 args) PMOD_EXPORT void call_handle_error(void) { + dmalloc_touch_svalue(&throw_value); if (Pike_interpreter.svalue_stack_margin) { ONERROR tmp; int old_t_flag = t_flag; diff --git a/src/interpret_functions.h b/src/interpret_functions.h index 1e28ae25b075738bedb514dd9b8fd195b68e66fa..d9a61dd7892c53568e3c5167cefcebc15c553305 100644 --- a/src/interpret_functions.h +++ b/src/interpret_functions.h @@ -1,5 +1,5 @@ /* - * $Id: interpret_functions.h,v 1.96 2001/09/29 08:47:03 hubbe Exp $ + * $Id: interpret_functions.h,v 1.97 2001/10/05 01:30:13 hubbe Exp $ * * Opcode definitions for the interpreter. */ @@ -2210,8 +2210,15 @@ OPCODE0(F_THIS_OBJECT, "this_object", { OPCODE0(F_ZERO_TYPE, "zero_type", { if(Pike_sp[-1].type != T_INT) { - pop_stack(); - push_int(0); + if((Pike_sp[-1].type==T_OBJECT || Pike_sp[-1].type==T_FUNCTION) + && !Pike_sp[-1].u.object->prog) + { + pop_stack(); + push_int(NUMBER_DESTRUCTED); + }else{ + pop_stack(); + push_int(0); + } }else{ Pike_sp[-1].u.integer=Pike_sp[-1].subtype; Pike_sp[-1].subtype=NUMBER_NUMBER; diff --git a/src/las.c b/src/las.c index c95135220668d9e6dcc92d01517db18e80f12da1..7ddb285ba365ee8e91a7f923fb740eab79375f93 100644 --- a/src/las.c +++ b/src/las.c @@ -5,7 +5,7 @@ \*/ /**/ #include "global.h" -RCSID("$Id: las.c,v 1.270 2001/09/29 11:31:40 hubbe Exp $"); +RCSID("$Id: las.c,v 1.271 2001/10/05 01:30:13 hubbe Exp $"); #include "language.h" #include "interpret.h" @@ -1734,7 +1734,6 @@ node *recursive_add_call_arg(node *n, node *arg) return n; } - node *index_node(node *n, char *node_name, struct pike_string *id) { node *ret; @@ -1789,6 +1788,29 @@ node *index_node(node *n, char *node_name, struct pike_string *id) push_int(0); break; + case T_OBJECT: + case T_PROGRAM: +#if 1 + if(!(Pike_compiler->new_program->flags & PROGRAM_PASS_1_DONE)) + { + struct program *p; + if(Pike_sp[-1].type == T_OBJECT) + p=Pike_sp[-1].u.object->prog; + else + p=Pike_sp[-1].u.program; + + if(p && !(p->flags & PROGRAM_PASS_1_DONE)) + { + if(report_compiler_dependency(p)) + { + pop_stack(); + ref_push_object(placeholder_object); + break; + } + } + } +#endif + default: { ptrdiff_t c; @@ -1831,19 +1853,26 @@ node *index_node(node *n, char *node_name, struct pike_string *id) !Pike_sp[-1].u.integer && Pike_sp[-1].subtype==NUMBER_UNDEFINED) { - if (node_name) { - my_yyerror("Index '%s' not present in module '%s'.", - id->str, node_name); - } else { - my_yyerror("Index '%s' not present in module.", id->str); - } - - if (thrown.type != PIKE_T_UNKNOWN) { - push_svalue(&thrown); - low_safe_apply_handler("compile_exception", error_handler, compat_handler, 1); - if (IS_ZERO(sp-1)) yy_describe_exception(&thrown); + if(Pike_compiler->new_program->flags & PROGRAM_PASS_1_DONE) + { + if (node_name) { + my_yyerror("Index '%s' not present in module '%s'.", + id->str, node_name); + } else { + my_yyerror("Index '%s' not present in module.", id->str); + } + + if (thrown.type != PIKE_T_UNKNOWN) { + push_svalue(&thrown); + low_safe_apply_handler("compile_exception", error_handler, compat_handler, 1); + if (IS_ZERO(sp-1)) yy_describe_exception(&thrown); + pop_stack(); + free_svalue(&thrown); + } + }else{ + /* Hope it's there in pass 2 */ pop_stack(); - free_svalue(&thrown); + ref_push_object(placeholder_object); } } } diff --git a/src/object.c b/src/object.c index dc6853eb5b3ec5b886f97fa8beb9a52844b1f9f6..ced4af41f184763bc0569b37cd1c74c5434e81ed 100644 --- a/src/object.c +++ b/src/object.c @@ -5,7 +5,7 @@ \*/ /**/ #include "global.h" -RCSID("$Id: object.c,v 1.185 2001/09/24 14:47:53 grubba Exp $"); +RCSID("$Id: object.c,v 1.186 2001/10/05 01:30:13 hubbe Exp $"); #include "object.h" #include "dynamic_buffer.h" #include "interpret.h" @@ -909,12 +909,14 @@ PMOD_EXPORT void low_object_index_no_free(struct svalue *to, switch(i->identifier_flags & (IDENTIFIER_FUNCTION | IDENTIFIER_CONSTANT)) { case IDENTIFIER_PIKE_FUNCTION: +#if 0 if (i->func.offset == -1) { /* prototype */ to->type=T_INT; to->subtype=NUMBER_UNDEFINED; to->u.integer=0; break; } +#endif case IDENTIFIER_FUNCTION: case IDENTIFIER_C_FUNCTION: to->type=T_FUNCTION; @@ -1030,7 +1032,7 @@ PMOD_EXPORT void object_index_no_free(struct svalue *to, struct svalue *index) { struct program *p = NULL; - int lfun; + int lfun,l; if(!o || !(p=o->prog)) { @@ -1039,7 +1041,23 @@ PMOD_EXPORT void object_index_no_free(struct svalue *to, } lfun=ARROW_INDEX_P(index) ? LFUN_ARROW : LFUN_INDEX; - if(FIND_LFUN(p, lfun) != -1) + if(p->flags & PROGRAM_FIXED) + { + l=p->lfuns[lfun]; + }else{ + if(!(p->flags & PROGRAM_PASS_1_DONE)) + { + if(report_compiler_dependency(p)) + { +/* fprintf(stderr,"PLACEHOLDER DEPLOYED\n"); */ + add_ref(to->u.object=placeholder_object); + to->type=T_OBJECT; + return; + } + } + l=low_find_lfun(p, lfun); + } + if(l != -1) { push_svalue(index); apply_lfun(o,lfun,1); diff --git a/src/pike_types.c b/src/pike_types.c index c632205d8058d3f29cb30ba3a440217c221abe8f..5f36be8b253cb6d03c94552d65096712ec2482ba 100644 --- a/src/pike_types.c +++ b/src/pike_types.c @@ -5,7 +5,7 @@ \*/ /**/ #include "global.h" -RCSID("$Id: pike_types.c,v 1.181 2001/08/20 18:08:50 mast Exp $"); +RCSID("$Id: pike_types.c,v 1.182 2001/10/05 01:30:13 hubbe Exp $"); #include <ctype.h> #include "svalue.h" #include "pike_types.h" @@ -29,7 +29,7 @@ RCSID("$Id: pike_types.c,v 1.181 2001/08/20 18:08:50 mast Exp $"); #include "block_alloc.h" #ifdef PIKE_DEBUG -#define PIKE_TYPE_DEBUG +/* #define PIKE_TYPE_DEBUG */ #endif /* PIKE_DEBUG */ /* diff --git a/src/program.c b/src/program.c index 0749beaaefc501648d1963629e249b6052dbc64c..b645df89930ecb4c1df9a0c2908b1e2c7e454049 100644 --- a/src/program.c +++ b/src/program.c @@ -5,7 +5,7 @@ \*/ /**/ #include "global.h" -RCSID("$Id: program.c,v 1.380 2001/10/02 09:08:19 hubbe Exp $"); +RCSID("$Id: program.c,v 1.381 2001/10/05 01:30:14 hubbe Exp $"); #include "program.h" #include "object.h" #include "dynamic_buffer.h" @@ -2002,7 +2002,6 @@ struct program *end_first_pass(int finish) Pike_compiler->new_program->flags |= PROGRAM_PASS_1_DONE; - if(finish) { if(Pike_compiler->new_program->flags & PROGRAM_USES_PARENT) @@ -4419,134 +4418,219 @@ void yy_describe_exception(struct svalue *thrown) } } -struct program *compile(struct pike_string *prog, - struct object *handler,/* error handler */ - int major, int minor, - struct program *target, - struct object *placeholder) -{ +extern void yyparse(void); + #ifdef PIKE_DEBUG - ONERROR tmp; +#define do_yyparse() do { \ + struct svalue *save_sp=Pike_sp; \ + yyparse(); /* Parse da program */ \ + if(save_sp != Pike_sp) \ + fatal("yyparse() left droppings on the stack!\n"); \ +}while(0) +#else +#define do_yyparse() yyparse() #endif + +struct compilation +{ + struct pike_string *prog; + struct object *handler; + int major, minor; + struct program *target; + struct object *placeholder; + struct program *p; struct lex save_lex; - int save_depth=compilation_depth; + int save_depth; int saved_threads_disabled; - struct object *saved_handler = error_handler; - struct object *saved_compat_handler = compat_handler; - dynamic_buffer used_modules_save = used_modules; - INT32 num_used_modules_save = Pike_compiler->num_used_modules; - extern void yyparse(void); - struct mapping *resolve_cache_save = resolve_cache; - resolve_cache = 0; - - CDFPRINTF((stderr, "th(%ld) compile() starting compilation_depth=%d\n", - (long)th_self(),compilation_depth)); - - if(placeholder && placeholder->prog != null_program) - Pike_error("Placeholder object is not a null_program clone!\n"); + struct object *saved_handler; + struct object *saved_compat_handler; + dynamic_buffer used_modules_save; + INT32 num_used_modules_save; + struct mapping *resolve_cache_save; - if(target && !(target->flags & PROGRAM_VIRGIN)) - Pike_error("Placeholder program is not virgin!\n"); + struct svalue default_module; - low_init_threads_disable(); - saved_threads_disabled = threads_disabled; + struct compilation *dependants; + struct compilation *next_dependant; +}; - CDFPRINTF((stderr, - "th(%ld) compile() Start: threads_disabled:%d, compilation_depth:%d\n", - (long)th_self(), threads_disabled, compilation_depth)); +static void free_compilation(struct compilation *c) +{ + debug_malloc_touch(c); + free_string(c->prog); + if(c->handler) free_object(c->handler); + if(c->target) free_program(c->target); + if(c->placeholder) free_object(c->placeholder); + free_svalue(& c->default_module); + free((char *)c); +} +static void run_init(struct compilation *c) +{ + debug_malloc_touch(c); + c->save_depth=compilation_depth; + compilation_depth=-1; -#ifdef PIKE_DEBUG - SET_ONERROR(tmp, fatal_on_error,"Compiler exited with longjump!\n"); -#endif + c->saved_handler = error_handler; + if((error_handler = c->handler)) + add_ref(error_handler); - error_handler = handler; + c->saved_compat_handler = compat_handler; compat_handler=0; - - if(error_handler) - { - add_ref(error_handler); - safe_apply(error_handler,"get_default_module",0); - if(IS_ZERO(Pike_sp-1)) - { - pop_stack(); - ref_push_mapping(get_builtin_constants()); - } - }else{ - ref_push_mapping(get_builtin_constants()); - } + c->used_modules_save = used_modules; + c->num_used_modules_save = Pike_compiler->num_used_modules; Pike_compiler->num_used_modules=0; - save_lex=lex; + c->resolve_cache_save = resolve_cache; + resolve_cache = 0; - lex.end = prog->str + (prog->len << prog->size_shift); - - switch(prog->size_shift) { - case 0: - lex.current_lexer = yylex0; - break; - case 1: - lex.current_lexer = yylex1; - break; - case 2: - lex.current_lexer = yylex2; - break; - default: - fatal("Program has bad shift %d!\n", prog->size_shift); - break; - } + c->save_lex=lex; lex.current_line=1; lex.current_file=make_shared_string("-"); - if (runtime_options & RUNTIME_STRICT_TYPES) { + + if (runtime_options & RUNTIME_STRICT_TYPES) + { lex.pragmas = ID_STRICT_TYPES; } else { lex.pragmas = 0; } - compilation_depth=-1; - low_start_new_program(target,0,0,0); + lex.end = c->prog->str + (c->prog->len << c->prog->size_shift); + + switch(c->prog->size_shift) + { + case 0: lex.current_lexer = yylex0; break; + case 1: lex.current_lexer = yylex1; break; + case 2: lex.current_lexer = yylex2; break; + default: + fatal("Program has bad shift %d!\n", c->prog->size_shift); + break; + } + + lex.pos=c->prog->str; +} + +static void run_init2(struct compilation *c) +{ + debug_malloc_touch(c); + Pike_compiler->compiler = c; initialize_buf(&used_modules); - use_module(Pike_sp-1); + use_module(& c->default_module); + + Pike_compiler->compat_major=PIKE_MAJOR_VERSION; + Pike_compiler->compat_minor=PIKE_MINOR_VERSION; + + if(c->major>=0) + change_compiler_compatibility(c->major, c->minor); +} + +static void run_exit(struct compilation *c) +{ + debug_malloc_touch(c); + toss_buffer(&used_modules); + used_modules = c->used_modules_save; + +#ifdef PIKE_DEBUG + if(Pike_compiler->num_used_modules) + fatal("Failed to pop modules properly.\n"); +#endif + Pike_compiler->num_used_modules = c->num_used_modules_save ; + +#ifdef PIKE_DEBUG + if (compilation_depth != -1) { + fprintf(stderr, "compile(): compilation_depth is %d\n", + compilation_depth); + } +#endif /* PIKE_DEBUG */ + compilation_depth=c->save_depth; + +#ifdef PIKE_DEBUG + if (resolve_cache) + free_mapping(resolve_cache); +#endif + resolve_cache = c->resolve_cache_save; + + if (error_handler) free_object(error_handler); + error_handler = c->saved_handler; + + if (compat_handler) free_object(compat_handler); + compat_handler = c->saved_compat_handler; + + free_string(lex.current_file); + lex=c->save_lex; +} + +static void zap_placeholder(struct compilation *c) +{ + /* fprintf(stderr, "Destructing placeholder.\n"); */ + if (c->placeholder->storage) { + yyerror("Placeholder already has storage!"); + /* fprintf(stderr, "Placeholder already has storage!\n" + "placeholder: %p, storage: %p, prog: %p, p: %p\n", + placeholder, placeholder->storage, placeholder->prog, p); */ + debug_malloc_touch(c->placeholder); + destruct(c->placeholder); + } else { + /* FIXME: Is this correct? */ + /* It would probably be nicer if it was possible to just call + * destruct on the object, but this works too. -Hubbe + */ + free_program(c->placeholder->prog); + c->placeholder->prog = NULL; + debug_malloc_touch(c->placeholder); + } + free_object(c->placeholder); + c->placeholder=0; +} + +static int run_pass1(struct compilation *c) +{ + int ret=0; + + debug_malloc_touch(c); + run_init(c); + + CDFPRINTF((stderr, "th(%ld) compile() starting compilation_depth=%d\n", + (long)th_self(),compilation_depth)); + + if(c->placeholder && c->placeholder->prog != null_program) + Pike_error("Placeholder object is not a null_program clone!\n"); + + if(c->target && !(c->target->flags & PROGRAM_VIRGIN)) + Pike_error("Placeholder program is not virgin!\n"); + + CDFPRINTF((stderr, + "th(%ld) compile() Start: threads_disabled:%d, compilation_depth:%d\n", + (long)th_self(), threads_disabled, compilation_depth)); + + + low_start_new_program(c->target,0,0,0); + Pike_compiler->compiler_pass=1; + run_init2(c); - if(placeholder) + if(c->placeholder) { - if(placeholder->prog != null_program) + if(c->placeholder->prog != null_program) { yyerror("Placeholder argument is not a null_program clone!"); - placeholder=0; + c->placeholder=0; + debug_malloc_touch(c->placeholder); }else{ - free_program(placeholder->prog); - add_ref(placeholder->prog=Pike_compiler->new_program); + free_program(c->placeholder->prog); + add_ref(c->placeholder->prog=Pike_compiler->new_program); + debug_malloc_touch(c->placeholder); } } -/* start_line_numbering(); */ - - Pike_compiler->compat_major=PIKE_MAJOR_VERSION; - Pike_compiler->compat_minor=PIKE_MINOR_VERSION; - Pike_compiler->compiler_pass=1; - lex.pos=prog->str; - - if(major>=0) - change_compiler_compatibility(major, minor); CDFPRINTF((stderr, "th(%ld) compile(): First pass\n", (long)th_self())); -#ifdef PIKE_DEBUG - { - struct svalue *save_sp=Pike_sp; - yyparse(); /* Parse da program */ - if(save_sp != Pike_sp) - fatal("yyparse() left droppings on the stack!\n"); - } -#else - yyparse(); /* Parse da program */ -#endif + do_yyparse(); /* Parse da program */ if (!Pike_compiler->new_program->num_linenumbers) { /* The lexer didn't write an initial entry. */ @@ -4560,163 +4644,229 @@ struct program *compile(struct pike_string *prog, CDFPRINTF((stderr, "th(%ld) compile(): First pass done\n", (long)th_self())); - p=end_first_pass(0); + if(Pike_compiler->depends_on) + { + ret++; + c->next_dependant=Pike_compiler->depends_on->compiler->dependants; + Pike_compiler->depends_on->compiler->dependants=c; +#if 0 + fprintf(stderr,"We (%p) should link ourself to %p\n", + c, + Pike_compiler->depends_on->compiler); +#endif + } + + c->p=end_first_pass(0); - if(placeholder) + run_exit(c); + + if(c->placeholder) { - if(!p || (placeholder->storage)) + if(!c->p || (c->placeholder->storage)) { - /* fprintf(stderr, "Destructing placeholder.\n"); */ - if (placeholder->storage) { - yyerror("Placeholder already has storage!"); - /* fprintf(stderr, "Placeholder already has storage!\n" - "placeholder: %p, storage: %p, prog: %p, p: %p\n", - placeholder, placeholder->storage, placeholder->prog, p); */ - debug_malloc_touch(placeholder); - destruct(placeholder); - } else { - /* FIXME: Is this correct? */ - /* It would probably be nicer if it was possible to just call - * destruct on the object, but this works too. -Hubbe - */ - free_program(placeholder->prog); - placeholder->prog = NULL; - } - placeholder=0; + zap_placeholder(c); } else { - placeholder->storage=p->storage_needed ? - (char *)xalloc(p->storage_needed) : + c->placeholder->storage=c->p->storage_needed ? + (char *)xalloc(c->p->storage_needed) : (char *)0; - call_c_initializers(placeholder); + call_c_initializers(c->placeholder); } } -#ifdef PIKE_DEBUG - if (compilation_depth != -1) { - fprintf(stderr, "compile(): compilation_depth is %d at end of pass 1.\n", - compilation_depth); - } -#endif /* PIKE_DEBUG */ + return ret; +} - if(p) - { - low_start_new_program(p,0,0,0); - free_program(p); - p=0; - Pike_compiler->compiler_pass=2; - lex.pos=prog->str; - lex.current_line=1; - free_string(lex.current_file); - lex.current_file=make_shared_string("-"); +void run_pass2(struct compilation *c) +{ + debug_malloc_touch(c); + run_init(c); + low_start_new_program(c->p,0,0,0); + free_program(c->p); + c->p=0; + Pike_compiler->compiler_pass=2; + run_init2(c); + + CDFPRINTF((stderr, "th(%ld) compile(): Second pass\n", + (long)th_self())); + + do_yyparse(); /* Parse da program */ + + CDFPRINTF((stderr, "th(%ld) compile(): Second pass done\n", + (long)th_self())); + + c->p=end_program(); + run_exit(c); +} - use_module(Pike_sp-1); +static void run_cleanup(struct compilation *c, int delayed) +{ + debug_malloc_touch(c); +#if 0 /* FIXME */ + if (threads_disabled != c->saved_threads_disabled) { + fatal("compile(): threads_disabled:%d saved_threads_disabled:%d\n", + threads_disabled, c->saved_threads_disabled); + } +#endif /* PIKE_DEBUG */ - if(major>=0) - change_compiler_compatibility(major, minor); + exit_threads_disable(NULL); - CDFPRINTF((stderr, "th(%ld) compile(): Second pass\n", - (long)th_self())); + CDFPRINTF((stderr, + "th(%ld) compile() Leave: threads_disabled:%d, compilation_depth:%d\n", + (long)th_self(),threads_disabled, compilation_depth)); + if (!c->p) + { + /* fprintf(stderr, "Destructing placeholder.\n"); */ + if(c->placeholder) + zap_placeholder(c); -#ifdef PIKE_DEBUG + if(delayed && c->target) { - struct svalue *save_sp=Pike_sp; - yyparse(); /* Parse da program */ - if(save_sp != Pike_sp) - fatal("yyparse() left droppings on the stack!\n"); + /* We have to notify the master object that + * a previous compile() actually failed, even + * if we did not know it at the time + */ + push_program(c->target); + SAFE_APPLY_MASTER("unregister",1); } -#else - yyparse(); /* Parse da program */ -#endif - - CDFPRINTF((stderr, "th(%ld) compile(): Second pass done\n", - (long)th_self())); - - p=end_program(); - -#ifdef PIKE_DEBUG - if (compilation_depth != -1) { - fprintf(stderr, "compile(): compilation_depth is %d at end of pass 2.\n", - compilation_depth); + } + else + { + if (c->placeholder) + { + JMP_BUF rec; + /* Initialize the placeholder. */ + if(SETJMP(rec)) + { + dmalloc_touch_svalue(&throw_value); + call_handle_error(); + zap_placeholder(c); + }else{ + call_pike_initializers(c->placeholder,0); + } + UNSETJMP(rec); } -#endif /* PIKE_DEBUG */ } +} +struct program *compile(struct pike_string *aprog, + struct object *ahandler,/* error handler */ + int amajor, int aminor, + struct program *atarget, + struct object *aplaceholder) +{ + int delay; + struct program *ret; #ifdef PIKE_DEBUG - if (threads_disabled != saved_threads_disabled) { - fatal("compile(): threads_disabled:%d saved_threads_disabled:%d\n", - threads_disabled, saved_threads_disabled); + ONERROR tmp; +#endif + struct compilation *c=ALLOC_STRUCT(compilation); + + debug_malloc_touch(c); + add_ref(c->prog=aprog); + if((c->handler=ahandler)) add_ref(ahandler); + c->major=amajor; + c->minor=aminor; + if((c->target=atarget)) add_ref(atarget); + if((c->placeholder=aplaceholder)) add_ref(aplaceholder); + c->default_module.type=T_INT; + c->dependants=0; + c->next_dependant=0; + + if(c->handler) + { + safe_apply(c->handler,"get_default_module",0); + if(IS_ZERO(Pike_sp-1)) + { + pop_stack(); + ref_push_mapping(get_builtin_constants()); + } + }else{ + ref_push_mapping(get_builtin_constants()); } -#endif /* PIKE_DEBUG */ + free_svalue(& c->default_module); + c->default_module=Pike_sp[-1]; + Pike_sp--; - free_string(lex.current_file); - lex=save_lex; - -/* unuse_modules(1); */ #ifdef PIKE_DEBUG - if(Pike_compiler->num_used_modules) - fatal("Failed to pop modules properly.\n"); + SET_ONERROR(tmp, fatal_on_error,"Compiler exited with longjump!\n"); #endif - toss_buffer(&used_modules); - compilation_depth=save_depth; - used_modules = used_modules_save; - Pike_compiler->num_used_modules = num_used_modules_save ; - if (error_handler) { - free_object(error_handler); - } - error_handler = saved_handler; - if (compat_handler) { - free_object(compat_handler); - } - compat_handler = saved_compat_handler; + low_init_threads_disable(); + c->saved_threads_disabled = threads_disabled; + + + delay=run_pass1(c) && c->p; + + while(c->dependants) + { + struct compilation *cc=c->dependants; + #ifdef PIKE_DEBUG - if (resolve_cache) fatal("resolve_cache not freed at end of compilation.\n"); + if(c == cc) + fatal("Depending on myself???\n"); #endif - resolve_cache = resolve_cache_save; -/* threads_disabled = saved_threads_disabled + 1; /Hubbe: UGGA! */ + c->dependants=cc->next_dependant; + cc->next_dependant=0; + debug_malloc_touch(cc); - CDFPRINTF((stderr, - "th(%ld) compile() Leave: threads_disabled:%d, compilation_depth:%d\n", - (long)th_self(),threads_disabled, compilation_depth)); + if(cc->p) run_pass2(cc); + run_cleanup(cc,1); - exit_threads_disable(NULL); + debug_malloc_touch(cc); + +#ifdef PIKE_DEBUG + if(cc->dependants) + fatal("Que???\n"); +#endif + + free_compilation(cc); + } #ifdef PIKE_DEBUG + /* FIXME */ UNSET_ONERROR(tmp); #endif - pop_stack(); /* pop the 'default' module */ - if (!p) { - /* fprintf(stderr, "Destructing placeholder.\n"); */ - if(placeholder) - { - if (placeholder->storage) { - /* fprintf(stderr, "Placeholder already has storage!\n" - "placeholder: %p, storage: %p, prog: %p, p: %p\n", - placeholder, placeholder->storage, placeholder->prog, p); */ - debug_malloc_touch(placeholder); - destruct(placeholder); - } else { - /* FIXME: Is this correct? */ - /* It would probably be nicer if it was possible to just call - * destruct on the object, but this works too. -Hubbe - */ - free_program(placeholder->prog); - placeholder->prog = NULL; - } - placeholder=0; - } + if(delay) + { + /* finish later */ + return c->p; + }else{ + /* finish now */ + if(c->p) run_pass2(c); + debug_malloc_touch(c); + run_cleanup(c,0); + + ret=c->p; - throw_error_object(low_clone(compilation_error_program), 0, 0, 0, - "Compilation failed.\n"); + debug_malloc_touch(c); + free_compilation(c); + if(!ret) + throw_error_object(low_clone(compilation_error_program), 0, 0, 0, + "Compilation failed.\n"); + return ret; } +} - if (placeholder) { - /* Initialize the placeholder. */ - call_pike_initializers(placeholder,0); +int report_compiler_dependency(struct program *p) +{ + if(Pike_compiler && Pike_compiler->new_program && + !(Pike_compiler->new_program->flags & PROGRAM_PASS_1_DONE)) + { + struct program_state *c; + c=Pike_compiler->depends_on; + if(!c) c=Pike_compiler->previous; + for(;c;c=c->previous) + { + if(c->new_program == p) + { + Pike_compiler->depends_on=c; + return 1; /* dependency registred */ + } + } } - return p; + return 0; /* dependency not registred */ } PMOD_EXPORT int pike_add_function2(char *name, void (*cfun)(INT32), @@ -4902,6 +5052,19 @@ static void gc_recurse_trampoline(struct object *o) } +/* This placeholder should is used + * in the first compiler pass to take the place + * of unknown things + */ +struct program *placeholder_program; +struct object *placeholder_object; + +void placeholder_index(INT32 args) +{ + pop_n_elems(args); + ref_push_object(Pike_fp->current_object); +} + void init_program(void) { int i; @@ -4910,7 +5073,6 @@ void init_program(void) struct svalue id; init_program_blocks(); - MAKE_CONSTANT_SHARED_STRING(this_program_string,"this_program"); lfun_ids = allocate_mapping(NUM_LFUNS); @@ -4952,6 +5114,20 @@ void init_program(void) low_add_constant("__null_program",&s); debug_malloc_touch(null_program); } + + { + struct svalue s; + start_new_program(); + add_function("`()",placeholder_index,"function(mixed...:object)",0); + add_function("`[]",placeholder_index,"function(mixed:object)",0); + placeholder_program=end_program(); + placeholder_object=fast_clone_object(placeholder_program,0); + + s.type=T_OBJECT; + s.u.object=placeholder_object; + low_add_constant("__placeholder_object",&s); + debug_malloc_touch(placeholder_object); + } } void cleanup_program(void) @@ -4994,6 +5170,18 @@ void cleanup_program(void) free_program(null_program); null_program=0; } + + if(placeholder_object) + { + free_object(placeholder_object); + placeholder_object=0; + } + + if(placeholder_program) + { + free_program(placeholder_program); + placeholder_program=0; + } #endif } diff --git a/src/program.h b/src/program.h index 1950555c8460fc73280b31469ecee85974013546..36c3fac993b48201f6841ffeaa059ddcc7735232 100644 --- a/src/program.h +++ b/src/program.h @@ -5,7 +5,7 @@ \*/ /* - * $Id: program.h,v 1.144 2001/09/10 20:47:35 hubbe Exp $ + * $Id: program.h,v 1.145 2001/10/05 01:30:14 hubbe Exp $ */ #ifndef PROGRAM_H #define PROGRAM_H @@ -345,6 +345,8 @@ extern struct object *compat_handler; extern struct program *first_program; extern struct program *pike_trampoline_program; extern struct program *gc_internal_program; +extern struct program *placeholder_program; +extern struct object *placeholder_object; extern int compilation_depth; @@ -380,7 +382,6 @@ void low_start_new_program(struct program *p, int flags, int *idp); PMOD_EXPORT void debug_start_new_program(PROGRAM_LINE_ARGS); -PMOD_EXPORT void really_free_program(struct program *p); void dump_program_desc(struct program *p); int sizeof_variable(int run_time_type); void check_program(struct program *p); @@ -393,7 +394,7 @@ PMOD_EXPORT void set_exit_callback(void (*exit)(struct object *)); PMOD_EXPORT void set_gc_recurse_callback(void (*m)(struct object *)); PMOD_EXPORT void set_gc_check_callback(void (*m)(struct object *)); void pike_set_prog_event_callback(void (*cb)(int)); -void pike_set_prog_optimize_callback(struct node_s *(*opt)(struct node_s *)); +void pike_set_prog_optimize_callback(node *(*opt)(node *)); int low_reference_inherited_identifier(struct program_state *q, int e, struct pike_string *name, @@ -440,35 +441,34 @@ int define_variable(struct pike_string *name, struct pike_type *type, INT32 flags); PMOD_EXPORT int simple_add_variable(char *name, - char *type, - INT32 flags); + char *type, + INT32 flags); PMOD_EXPORT int add_constant(struct pike_string *name, - struct svalue *c, - INT32 flags); + struct svalue *c, + INT32 flags); PMOD_EXPORT int simple_add_constant(char *name, - struct svalue *c, - INT32 flags); + struct svalue *c, + INT32 flags); PMOD_EXPORT int add_integer_constant(char *name, - INT32 i, - INT32 flags); + INT32 i, + INT32 flags); PMOD_EXPORT int quick_add_integer_constant(char *name, - int name_length, - INT32 i, - INT32 flags); + int name_length, + INT32 i, + INT32 flags); PMOD_EXPORT int add_float_constant(char *name, - double f, - INT32 flags); + double f, + INT32 flags); PMOD_EXPORT int add_string_constant(char *name, - char *str, - INT32 flags); + char *str, + INT32 flags); PMOD_EXPORT int add_program_constant(char *name, - struct program *p, - INT32 flags); + struct program *p, + INT32 flags); PMOD_EXPORT int add_object_constant(char *name, - struct object *o, - INT32 flags); -PMOD_EXPORT int add_function_constant(char *name, void (*cfun)(INT32), - char * type, INT16 flags); + struct object *o, + INT32 flags); +PMOD_EXPORT int add_function_constant(char *name, void (*cfun)(INT32), char * type, INT16 flags); PMOD_EXPORT int debug_end_class(char *name, ptrdiff_t namelen, INT32 flags); INT32 define_function(struct pike_string *name, struct pike_type *type, @@ -498,21 +498,22 @@ void program_index_no_free(struct svalue *to, struct program *p, int get_small_number(char **q); void start_line_numbering(void); void store_linenumber(INT32 current_line, struct pike_string *current_file); -char *debug_get_program_line(struct program *prog, - INT32 *linep); PMOD_EXPORT struct pike_string *get_program_line(struct program *prog, INT32 *linep); +char *debug_get_program_line(struct program *prog, + INT32 *linep); PMOD_EXPORT struct pike_string *get_line(PIKE_OPCODE_T *pc, - struct program *prog, - INT32 *linep); + struct program *prog, INT32 *linep); void my_yyerror(char *fmt,...) ATTRIBUTE((format(printf,1,2))); void yy_describe_exception(struct svalue *thrown); -struct program *compile(struct pike_string *prog, - struct object *handler, - int major, - int minor, - struct program *target, - struct object *placeholder); +struct compilation; +void run_pass2(struct compilation *c); +struct program *compile(struct pike_string *aprog, + struct object *ahandler, + int amajor, int aminor, + struct program *atarget, + struct object *aplaceholder); +int report_compiler_dependency(struct program *p); PMOD_EXPORT int pike_add_function2(char *name, void (*cfun)(INT32), char *type, unsigned INT8 flags, unsigned INT16 opt_flags); @@ -524,6 +525,7 @@ PMOD_EXPORT int quick_add_function(char *name, unsigned INT8 flags, unsigned INT16 opt_flags); void check_all_programs(void); +void placeholder_index(INT32 args); void init_program(void); void cleanup_program(void); void gc_mark_program_as_referenced(struct program *p); @@ -534,8 +536,8 @@ void gc_mark_all_programs(void); void gc_cycle_check_all_programs(void); void gc_zap_ext_weak_refs_in_programs(void); void gc_free_all_unreferenced_programs(void); -void count_memory_in_programs(INT32 *num_, INT32 *size_); void push_compiler_frame(int lexical_scope); +void low_pop_local_variables(int level); void pop_local_variables(int level); void pop_compiler_frame(void); ptrdiff_t low_get_storage(struct program *o, struct program *p); @@ -556,6 +558,9 @@ PMOD_EXPORT void change_compiler_compatibility(int major, int minor); void make_program_executable(struct program *p); /* Prototypes end here */ +void really_free_program(struct program *); +void count_memory_in_programs(INT32*,INT32*); + #ifndef PIKE_USE_MACHINE_CODE #define make_program_executable(X) #endif diff --git a/src/threads.c b/src/threads.c index e05114471019e426bd7e7e17a6dc5135b8538f06..ffc70a8a419c65aa23d6f0622508f7527132a8ed 100644 --- a/src/threads.c +++ b/src/threads.c @@ -1,5 +1,5 @@ #include "global.h" -RCSID("$Id: threads.c,v 1.168 2001/09/25 14:17:47 grubba Exp $"); +RCSID("$Id: threads.c,v 1.169 2001/10/05 01:30:14 hubbe Exp $"); PMOD_EXPORT int num_threads = 1; PMOD_EXPORT int threads_disabled = 0; @@ -922,7 +922,7 @@ void f_mutex_lock(INT32 args) /* Needs to be cloned here, since create() * might use threads. */ - o=clone_object(mutex_key,0); + o=fast_clone_object(mutex_key,0); DO_IF_DEBUG( if(thread_for_id(th_self()) != Pike_interpreter.thread_id) fatal("thread_for_id() (or Pike_interpreter.thread_id) failed! %p != %p\n",thread_for_id(th_self()),Pike_interpreter.thread_id) ; )