static PyObject* do_fullcompile(PyFrameObject* frame, PyObject* arg) { PyCodeStats* cs; cs = PyCodeStats_Get(frame->f_code); if (cs->st_codebuf == NULL) { /* not already compiled, compile it now */ PyObject* g = frame->f_globals; int rec, module; stats_printf(("stats: full compile code: %s\n", PyCodeObject_NAME(frame->f_code))); if (cs->st_globals && PyInt_Check(cs->st_globals)) rec = PyInt_AS_LONG(cs->st_globals); else rec = DEFAULT_RECURSION; module = frame->f_globals == frame->f_locals; cs->st_codebuf = PsycoCode_CompileCode(frame->f_code, g, rec, module); if (cs->st_codebuf == Py_None) g = NULL; /* failed */ else { Py_INCREF(g); extra_assert(CodeBuffer_Check(cs->st_codebuf)); } Py_XDECREF(cs->st_globals); cs->st_globals = g; } /* already compiled a Psyco version, run it if the globals match */ extra_assert(frame->f_globals != NULL); if (cs->st_globals == frame->f_globals) { Py_INCREF(cs->st_codebuf); return cs->st_codebuf; } return NULL; }
DEFINEFN void psyco_turbo_code(PyCodeObject* code, int recursion) { PyCodeStats* cs = PyCodeStats_Get(code); if (cs->st_codebuf == NULL && cs->st_globals == NULL) { /* trigger compilation at the next occasion by storing something non-NULL in st_globals */ cs->st_globals = PyInt_FromLong(recursion); if (cs->st_globals == NULL) OUT_OF_MEMORY(); } }
DEFINEFN void psyco_stats_append(PyThreadState* tstate, PyFrameObject* f) { double charge; float cs_charge; int bits; time_measure_t numticks; if (!measuring_state(tstate)) return; numticks = get_measure(tstate); if (measure_is_zero(numticks) || f == NULL) return; /* f==NULL must still make a get_measure() call */ charge = ((double) charge_unit) * numticks; bits = c_random(); while (1) { PyCodeStats* cs = PyCodeStats_Get(f->f_code); cs_charge = (float)(cs->st_charge + charge); cs->st_charge = cs_charge; charge_total += charge; if (cs_charge > charge_prelimit && charge_callback) { /* update charge_prelimit */ charge_prelimit = (float)(charge_total * charge_watermark); if (cs_charge > charge_prelimit) { /* still over the up-to-date limit */ cs->st_charge = 0.0f; break; } } if (bits >= 0) return; /* triggers in about 50% of the cases */ bits <<= 1; f = f->f_back; if (!f) return; charge *= charge_parent2; } /* charge limit reached, invoke callback */ { PyObject* r; r = PyObject_CallFunction(charge_callback, "Of", f, cs_charge); if (r == NULL) { PyErr_WriteUnraisable((PyObject*) f); } else { Py_DECREF(r); } } }
static PyObject* profile_call(PyFrameObject* frame, PyObject* arg) { PyCodeStats* cs; psyco_stats_append(frame->f_tstate, frame->f_back); cs = PyCodeStats_Get(frame->f_code); if (cs->st_globals != NULL) { /* we want to accelerate this code object */ if (cs->st_codebuf == NULL) { /* not already compiled, compile it now */ PyObject* codebuf; PyObject* g = frame->f_globals; int rec, module; stats_printf(("stats: compile code: %s\n", PyCodeObject_NAME(frame->f_code))); if (PyInt_Check(cs->st_globals)) rec = PyInt_AS_LONG(cs->st_globals); else rec = DEFAULT_RECURSION; module = frame->f_globals == frame->f_locals; codebuf = PsycoCode_CompileCode(frame->f_code, g, rec, module); /* rare race condition: 'cs' might have been mutated during the call to PsycoCode_CompileCode(), so cs->st_codebuf might no longer be NULL, or cs->st_globals might be NULL again */ Py_XDECREF(cs->st_codebuf); cs->st_codebuf = codebuf; if (cs->st_codebuf == Py_None) g = NULL; /* failed */ else { Py_INCREF(g); extra_assert (CodeBuffer_Check(cs->st_codebuf)); } Py_XDECREF(cs->st_globals); cs->st_globals = g; } /* already compiled a Psyco version, run it if the globals match */ extra_assert(frame->f_globals != NULL); if (cs->st_globals == frame->f_globals) { Py_INCREF(cs->st_codebuf); return cs->st_codebuf; } } return NULL; }