Update of /cvsroot/psyco/psyco/c In directory sc8-pr-cvs1:/tmp/cvs-serv5133/c Modified Files: dispatcher.c dispatcher.h processor.c profile.c psyco.h psyfunc.c stats.c stats.h vcompiler.c vcompiler.h Log Message: added bounds to avoid code size explosion Index: dispatcher.c =================================================================== RCS file: /cvsroot/psyco/psyco/c/dispatcher.c,v retrieving revision 1.29 retrieving revision 1.30 diff -C2 -d -r1.29 -r1.30 *** dispatcher.c 10 Feb 2003 17:09:33 -0000 1.29 --- dispatcher.c 9 Mar 2003 21:06:37 -0000 1.30 *************** *** 1859,1890 **** } - DEFINEFN - bool psyco_forking(PsycoObject* po, vinfo_array_t* array, bool force) - { - /* Some virtual-time objects cannot remain virtualized across calls, - because if the called function pulls them out of virtual-time, - the caller will not know it. This is unacceptable for - mutable Python objects. We hope it does not hurt in other cases, - but could be defeated by the "is" operator. */ - int i; - for (i=array->count; i--; ) - { - vinfo_t* vi = array->items[i]; - if (vi != NULL) - { - if (is_virtualtime(vi->source)) - { - if (!VirtualTime_Get(vi->source)->compute_fn(po, vi, force)) - return false; - /* vi->array may be modified by compute_fn() */ - } - if (vi->array != NullArray) - if (!psyco_forking(po, vi->array, force)) - return false; - } - } - return true; - } - static void remove_non_compiletime(vinfo_t* v, PsycoObject* po) { --- 1859,1862 ---- Index: dispatcher.h =================================================================== RCS file: /cvsroot/psyco/psyco/c/dispatcher.h,v retrieving revision 1.15 retrieving revision 1.16 diff -C2 -d -r1.15 -r1.16 *** dispatcher.h 31 Jan 2003 13:46:51 -0000 1.15 --- dispatcher.h 9 Mar 2003 21:06:39 -0000 1.16 *************** *** 174,178 **** /* Emit the code to prepare for Psyco code calling Psyco code in a compiled function call */ ! EXTERNFN bool psyco_forking(PsycoObject* po, vinfo_array_t* array, bool force); /*****************************************************************/ --- 174,186 ---- /* Emit the code to prepare for Psyco code calling Psyco code in a compiled function call */ ! inline bool psyco_forking(PsycoObject* po, vinfo_array_t* array) { ! /* Some virtual-time objects cannot remain virtualized across calls, ! because if the called function pulls them out of virtual-time, ! the caller will not know it. This is unacceptable for ! mutable Python objects. We hope it does not hurt in other cases, ! but could be defeated by the "is" operator. */ ! return psyco_limit_nested_weight(po, array, NWI_FUNCALL, ! NESTED_WEIGHT_END); ! } /*****************************************************************/ Index: processor.c =================================================================== RCS file: /cvsroot/psyco/psyco/c/processor.c,v retrieving revision 1.23 retrieving revision 1.24 diff -C2 -d -r1.23 -r1.24 *** processor.c 10 Feb 2003 17:09:34 -0000 1.23 --- processor.c 9 Mar 2003 21:06:39 -0000 1.24 *************** *** 687,694 **** /*** Condition Codes (a.k.a. the processor 'flags' register) ***/ ! typedef struct { ! source_virtual_t header; ! code_t cc; ! } computed_cc_t; /* internal, see NEED_CC() */ --- 687,697 ---- /*** Condition Codes (a.k.a. the processor 'flags' register) ***/ ! static source_virtual_t cc_functions_table[CC_TOTAL]; ! ! inline condition_code_t cc_from_vsource(Source source) ! { ! source_virtual_t* sv = VirtualTime_Get(source); ! return (condition_code_t) (sv - cc_functions_table); ! } /* internal, see NEED_CC() */ *************** *** 697,705 **** { vinfo_t* v = po->ccreg; ! computed_cc_t* cc = (computed_cc_t*) VirtualTime_Get(v->source); reg_t rg; NEED_FREE_BYTE_REG(rg, reserved, REG_NONE); ! LOAD_REG_FROM_CONDITION(rg, cc->cc); v->source = RunTime_New(rg, false, true); --- 700,708 ---- { vinfo_t* v = po->ccreg; ! condition_code_t cc = cc_from_vsource(v->source); reg_t rg; NEED_FREE_BYTE_REG(rg, reserved, REG_NONE); ! LOAD_REG_FROM_CONDITION(rg, cc); v->source = RunTime_New(rg, false, true); *************** *** 709,713 **** } ! static bool generic_computed_cc(PsycoObject* po, vinfo_t* v, bool force) { /* also upon forking, because the condition codes cannot be --- 712,716 ---- } ! static bool generic_computed_cc(PsycoObject* po, vinfo_t* v) { /* also upon forking, because the condition codes cannot be *************** *** 721,726 **** } - static computed_cc_t cc_functions_table[CC_TOTAL]; - DEFINEFN --- 724,727 ---- *************** *** 748,753 **** } extra_assert(po->ccreg == NULL); ! po->ccreg = vinfo_new(VirtualTime_New ! (&cc_functions_table[(int)cc].header)); result = po->ccreg; } --- 749,753 ---- } extra_assert(po->ccreg == NULL); ! po->ccreg = vinfo_new(VirtualTime_New(cc_functions_table+(int)cc)); result = po->ccreg; } *************** *** 762,769 **** if (is_virtualtime(source)) { ! computed_cc_t* s = (computed_cc_t*) VirtualTime_Get(source); ! long result = s - cc_functions_table; ! if (0 <= result && result < CC_TOTAL) ! return (condition_code_t) result; } return CC_ALWAYS_FALSE; --- 762,771 ---- if (is_virtualtime(source)) { ! source_virtual_t* sv = VirtualTime_Get(source); ! if (cc_functions_table <= sv && sv < cc_functions_table+CC_TOTAL) ! { ! /* 'sv' points within the cc_functions_table */ ! return cc_from_vsource(source); ! } } return CC_ALWAYS_FALSE; *************** *** 786,790 **** ! static bool computed_promotion(PsycoObject* po, vinfo_t* v, bool force); /* forward */ --- 788,792 ---- ! static bool computed_promotion(PsycoObject* po, vinfo_t* v); /* forward */ *************** *** 803,808 **** for (i=0; i<CC_TOTAL; i++) { ! cc_functions_table[i].header.compute_fn = &generic_computed_cc; ! cc_functions_table[i].cc = (condition_code_t) i; } psyco_nonfixed_promotion.header.compute_fn = &computed_promotion; --- 805,811 ---- for (i=0; i<CC_TOTAL; i++) { ! /* the condition codes cannot be passed across function calls, ! hence the NW_FORCE argument */ ! INIT_SVIRTUAL(cc_functions_table[i], generic_computed_cc, 0, NW_FORCE); } psyco_nonfixed_promotion.header.compute_fn = &computed_promotion; *************** *** 822,830 **** /*** run-time switches ***/ ! static bool computed_promotion(PsycoObject* po, vinfo_t* v, bool force) { /* uncomputable, but still use the address of computed_promotion() as a tag to figure out if a virtual source is a c_promotion_s structure. */ ! return psyco_vsource_not_important.compute_fn(po, v, force); } --- 825,833 ---- /*** run-time switches ***/ ! static bool computed_promotion(PsycoObject* po, vinfo_t* v) { /* uncomputable, but still use the address of computed_promotion() as a tag to figure out if a virtual source is a c_promotion_s structure. */ ! return psyco_vsource_not_important.compute_fn(po, v); } Index: profile.c =================================================================== RCS file: /cvsroot/psyco/psyco/c/profile.c,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** profile.c 4 Feb 2003 11:18:51 -0000 1.2 --- profile.c 9 Mar 2003 21:06:39 -0000 1.3 *************** *** 318,322 **** case 'l': /* "line" */ ! what = Pytrace_LINE; break; --- 318,322 ---- case 'l': /* "line" */ ! what = PyTrace_LINE; break; *************** *** 325,329 **** } frame = (PyFrameObject*) PyTuple_GET_ITEM(args, 0); ! if (!call_ceval_hooks(get_cevent(frame->f_tstate), what, frame)) return NULL; --- 325,329 ---- } frame = (PyFrameObject*) PyTuple_GET_ITEM(args, 0); ! if (!call_ceval_hooks(get_cevents(frame->f_tstate), what, frame)) return NULL; *************** *** 332,336 **** return obj_pwrapper; } ! static PyMethodDef def_profile_wrapper = { "wrapper", &profile_wrapper, METH_VARARGS }; #define SET_PYTHON_HOOKS(name, fn) { \ --- 332,336 ---- return obj_pwrapper; } ! static PyMethodDef def_profile_wrapper = { "wrapper", &trace_or_profile_wrapper, METH_VARARGS }; #define SET_PYTHON_HOOKS(name, fn) { \ *************** *** 441,446 **** return; istate = PyThreadState_Get()->interp; ! tstate = PyInterpreterState_ThreadHead(istate); ! for (; tstate; tstate = PyThreadState_Next(tstate)) { ceval_events_t* cev; if (!measuring_state(tstate)) --- 441,445 ---- return; istate = PyThreadState_Get()->interp; ! for (tstate=istate->tstate_head; tstate; tstate=tstate->next) { ceval_events_t* cev; if (!measuring_state(tstate)) *************** *** 748,753 **** (this might overlook pending generators) */ PyInterpreterState* istate = PyThreadState_Get()->interp; ! PyThreadState* tstate = PyInterpreterState_ThreadHead(istate); ! for (; tstate; tstate = PyThreadState_Next(tstate)) { PyFrameObject* f = tstate->frame; for (; f; f = f->f_back) { --- 747,752 ---- (this might overlook pending generators) */ PyInterpreterState* istate = PyThreadState_Get()->interp; ! PyThreadState* tstate; ! for (tstate=istate->tstate_head; tstate; tstate=tstate->next) { PyFrameObject* f = tstate->frame; for (; f; f = f->f_back) { Index: psyco.h =================================================================== RCS file: /cvsroot/psyco/psyco/c/psyco.h,v retrieving revision 1.28 retrieving revision 1.29 diff -C2 -d -r1.28 -r1.29 *** psyco.h 4 Feb 2003 20:17:28 -0000 1.28 --- psyco.h 9 Mar 2003 21:06:41 -0000 1.29 *************** *** 233,240 **** ! /* moved here from vcompiler.h because needed by numerous header files */ ! typedef bool (*compute_fn_t)(PsycoObject* po, vinfo_t* vi, bool force); typedef struct { compute_fn_t compute_fn; } source_virtual_t; --- 233,242 ---- ! /* moved here from vcompiler.h because needed by numerous header files. ! See vcompiler.h for comments */ ! typedef bool (*compute_fn_t)(PsycoObject* po, vinfo_t* vi); typedef struct { compute_fn_t compute_fn; + signed char nested_weight[2]; } source_virtual_t; Index: psyfunc.c =================================================================== RCS file: /cvsroot/psyco/psyco/c/psyfunc.c,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** psyfunc.c 4 Feb 2003 11:18:51 -0000 1.6 --- psyfunc.c 9 Mar 2003 21:06:42 -0000 1.7 *************** *** 267,271 **** /* This is expected to have already been done on default arguments; see PsycoFunction_New() */ ! if (!psyco_forking(po, arg_tuple->array, false)) return NULL; --- 267,271 ---- /* This is expected to have already been done on default arguments; see PsycoFunction_New() */ ! if (!psyco_forking(po, arg_tuple->array)) return NULL; Index: stats.c =================================================================== RCS file: /cvsroot/psyco/psyco/c/stats.c,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** stats.c 17 Jan 2003 14:41:13 -0000 1.1 --- stats.c 9 Mar 2003 21:06:42 -0000 1.2 *************** *** 44,47 **** --- 44,48 ---- } + #if HAVE_DYN_COMPILE DEFINEFN PyCodeStats* PyCodeStats_MaybeGet(PyCodeObject* co) *************** *** 49,52 **** --- 50,54 ---- return (PyCodeStats*) PyCStruct_DictGet(codestats_dict, (PyObject*) co); } + #endif *************** *** 237,242 **** /* collect statistics for all registered threads */ PyInterpreterState* istate = PyThreadState_Get()->interp; ! PyThreadState* tstate = PyInterpreterState_ThreadHead(istate); ! for (; tstate; tstate = PyThreadState_Next(tstate)) { psyco_stats_append(tstate, tstate->frame); } --- 239,244 ---- /* collect statistics for all registered threads */ PyInterpreterState* istate = PyThreadState_Get()->interp; ! PyThreadState* tstate; ! for (tstate=istate->tstate_head; tstate; tstate=tstate->next) { psyco_stats_append(tstate, tstate->frame); } *************** *** 273,279 **** #if MEASURE_ALL_THREADS PyInterpreterState* istate = PyThreadState_Get()->interp; ! PyThreadState* tstate = PyInterpreterState_ThreadHead(istate); ! for (; tstate; tstate = PyThreadState_Next(tstate)) (void) get_measure(tstate); #else (void) get_measure(NULL); --- 275,282 ---- #if MEASURE_ALL_THREADS PyInterpreterState* istate = PyThreadState_Get()->interp; ! PyThreadState* tstate; ! for (tstate=istate->tstate_head; tstate; tstate=tstate->next) { (void) get_measure(tstate); + } #else (void) get_measure(NULL); Index: stats.h =================================================================== RCS file: /cvsroot/psyco/psyco/c/stats.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** stats.h 17 Jan 2003 14:41:13 -0000 1.1 --- stats.h 9 Mar 2003 21:06:42 -0000 1.2 *************** *** 38,42 **** --- 38,44 ---- /* return the PyCodeStats for 'co' */ EXTERNFN PyCodeStats* PyCodeStats_Get(PyCodeObject* co); + #if HAVE_DYN_COMPILE EXTERNFN PyCodeStats* PyCodeStats_MaybeGet(PyCodeObject* co); + #endif /* compute and return a Borrowed reference to st_mergepoints */ Index: vcompiler.c =================================================================== RCS file: /cvsroot/psyco/psyco/c/vcompiler.c,v retrieving revision 1.21 retrieving revision 1.22 diff -C2 -d -r1.21 -r1.22 *** vcompiler.c 4 Feb 2003 20:17:29 -0000 1.21 --- vcompiler.c 9 Mar 2003 21:06:43 -0000 1.22 *************** *** 407,410 **** --- 407,442 ---- } + DEFINEFN + bool psyco_limit_nested_weight(PsycoObject* po, vinfo_array_t* array, + int nw_index, signed char nw_end) + { + signed char nw; + int i; + for (i=array->count; i--; ) + { + vinfo_t* vi = array->items[i]; + if (vi != NULL) + { + nw = nw_end; + if (is_virtualtime(vi->source)) + { + source_virtual_t* sv = VirtualTime_Get(vi->source); + nw -= sv->nested_weight[nw_index]; + if (nw <= 0) + { + /* maximum reached, force out of virtual-time */ + if (!sv->compute_fn(po, vi)) + return false; + /* vi->array may be modified by compute_fn() */ + continue; + } + } + if (vi->array != NullArray) + if (!psyco_limit_nested_weight(po, vi->array, nw_index, nw)) + return false; + } + } + return true; + } /*****************************************************************/ *************** *** 705,709 **** mergepoint_t* mp = psyco_exact_merge_point(po->pr.merge_points, po->pr.next_instr); ! extra_assert(psyco_locked_buffers() == 0); /* we are not compiling yet */ return (code_t*) psyco_compile_code(po, mp)->codestart; /* XXX don't know what to do with the reference returned by --- 737,742 ---- mergepoint_t* mp = psyco_exact_merge_point(po->pr.merge_points, po->pr.next_instr); ! /* check that we are not compiling recursively, or at least not too deeply */ ! extra_assert(psyco_locked_buffers() < WARN_TOO_MANY_BUFFERS-1); return (code_t*) psyco_compile_code(po, mp)->codestart; /* XXX don't know what to do with the reference returned by *************** *** 876,880 **** function that calls a function that needs compiling, recursively. Delay compilation until run-time, when psyco_locked_buffers() will ! be 0. */ psyco_coding_pause(po, CC_ALWAYS_TRUE, &psyco_resume_compile, NULL, 0); code1 = po->code; --- 909,913 ---- function that calls a function that needs compiling, recursively. Delay compilation until run-time, when psyco_locked_buffers() will ! be much smaller. */ psyco_coding_pause(po, CC_ALWAYS_TRUE, &psyco_resume_compile, NULL, 0); code1 = po->code; *************** *** 891,897 **** /*****************************************************************/ ! static bool computed_do_not_use(PsycoObject* po, vinfo_t* vi, bool force) { - if (!force) return true; fprintf(stderr, "psyco: internal error (computed_do_not_use)\n"); extra_assert(0); /* stop if debugging */ --- 924,929 ---- /*****************************************************************/ ! static bool computed_do_not_use(PsycoObject* po, vinfo_t* vi) { fprintf(stderr, "psyco: internal error (computed_do_not_use)\n"); extra_assert(0); /* stop if debugging */ *************** *** 903,907 **** void psyco_compiler_init(void) { ! psyco_vsource_not_important.compute_fn = &computed_do_not_use; } --- 935,939 ---- void psyco_compiler_init(void) { ! INIT_SVIRTUAL(psyco_vsource_not_important, computed_do_not_use, 0, 0); } Index: vcompiler.h =================================================================== RCS file: /cvsroot/psyco/psyco/c/vcompiler.h,v retrieving revision 1.15 retrieving revision 1.16 diff -C2 -d -r1.15 -r1.16 *** vcompiler.h 10 Feb 2003 17:09:39 -0000 1.15 --- vcompiler.h 9 Mar 2003 21:06:43 -0000 1.16 *************** *** 189,196 **** * * if the last two bits of 'source' are VIRTUAL_TIME, ! * the rest of 'source' points to a 'source_virtual_t' structure. ! * See psyco.h for the definition of source_virtual_t. * **/ /* construction */ --- 189,227 ---- * * if the last two bits of 'source' are VIRTUAL_TIME, ! * the rest of 'source' points to a 'source_virtual_t' structure (in psyco.h). ! * Description of the fields of source_virtual_t: ! * ! * compute_fn_t compute_fn; ! * the function to be called to move the vinfo_t out of virtual-time. * + * signed char nested_weight[2]; + * a value > 0 prevents infinite nesting of virtual 'vinfo_t's inside + * of other virtual 'vinfo_t's: the sum of all 'nested_weight' fields + * of a chain of nested 'vinfo_t's should always be less than + * NESTED_WEIGHT_END. There are two values because limiting some kind + * of virtual 'vinfo_t's is more important across function calls than + * inside the same function. **/ + #define NESTED_WEIGHT_END 15 + #define NWI_NORMAL 0 /* use nested_weight[0] */ + #define NWI_FUNCALL 1 /* use nested_weight[1] */ + #define INIT_SVIRTUAL(sv, fn, w_normal, w_funcall) do { \ + (sv).compute_fn = &fn; \ + (sv).nested_weight[NWI_NORMAL] = w_normal; \ + (sv).nested_weight[NWI_FUNCALL] = w_funcall; \ + } while (0) + + /* some weights for common virtual-time objects, grouped here to better + show their relative importance. A careful tuning is required to avoid + code size explosion. (The following figures are only a guess; some + real-code testing would be welcome.) */ + #define NW_VLISTS 5 + #define NW_TUPLES_NORMAL 4 + #define NW_TUPLES_FUNCALL 4 + #define NW_STRSLICES_NORMAL 5 + #define NW_STRSLICES_FUNCALL 9 + #define NW_CATSTRS_NORMAL 4 /* catstrs also have a vlist internally */ + #define NW_CATSTRS_FUNCALL 7 + #define NW_FORCE NESTED_WEIGHT_END /* always force */ /* construction */ *************** *** 297,301 **** inline bool compute_vinfo(vinfo_t* vi, PsycoObject* po) { if (is_virtualtime(vi->source)) { ! if (!VirtualTime_Get(vi->source)->compute_fn(po, vi, true)) return false; extra_assert(!is_virtualtime(vi->source)); --- 328,332 ---- inline bool compute_vinfo(vinfo_t* vi, PsycoObject* po) { if (is_virtualtime(vi->source)) { ! if (!VirtualTime_Get(vi->source)->compute_fn(po, vi)) return false; extra_assert(!is_virtualtime(vi->source)); *************** *** 303,306 **** --- 334,339 ---- return true; } + EXTERNFN bool psyco_limit_nested_weight(PsycoObject* po, vinfo_array_t* array, + int nw_index, signed char nw_end); inline bool vinfo_known_equal(vinfo_t* v, vinfo_t* w) { |