Commits

Mark Shannon committed bd241de Draft

Ensure exit counts are correct and various minor fixes

  • Participants
  • Parent commits f8d93e4

Comments (0)

Files changed (7)

Include/optimiser.h

 #include "trace_opcode.h"
 #include "structmember.h"
 
-#define HOTPY_CONTEXT_DEPTH 6
+#define HOTPY_CONTEXT_DEPTH 8
 
 typedef struct _hotpy_instruction_pointer {
     PyCodeObject *code;
     unsigned long off_trace;
     unsigned long trace_entries;
     unsigned long trace_transfers;
-    unsigned long mono_to_poly;
+    unsigned long mono_to_poly_exit;
     unsigned long polymorphic_cold_exits;
     unsigned long polymorphic_overflow_exits;
     unsigned long not_bool_exits;

Python/recording_interpreter.c

             /* FindTrace returns a new reference which Execute steals */
             int stack = tstate->real_frame->f_stacktop -
                         tstate->real_frame->f_valuestack;
-            hot_trace = HotPyTraceManager_FindTrace(tstate, retval.value, stack);
+            unsigned char *next_instr;
+            if (retval.value == NULL)
+                next_instr = _HotPy_NextInstruction(tstate->real_frame);
+            else
+                next_instr = retval.value;
+            hot_trace = HotPyTraceManager_FindTrace(tstate, next_instr, stack);
             if (hot_trace) {
-                assert(HotPyIP_ToAddr(hot_trace->trace_context->cf_instrs[0]) == retval.value);
+                assert(HotPyIP_ToAddr(hot_trace->trace_context->cf_instrs[0]) == next_instr);
                 retval = HotPyTrace_Execute(tstate, hot_trace);
                 if (tstate->real_frame == caller_frame)
                     break;
             retval.why = WHY_NOT;
             retval.value = NULL;
         }
-        retval = PyEval_EvalFrame_C(tstate, retval.value, retval.why);
+        else
+            retval = PyEval_EvalFrame_C(tstate, retval.value, retval.why);
     }
     assert(retval.why != WHY_NOT);
     assert(tstate->real_frame == caller_frame);
     builtins = PyDict_GetItemString(PyFunction_GET_GLOBALS(func), "__builtins__");
     if (PyModule_Check(builtins))
         builtins = PyObject_GetAttrString(builtins, "__dict__");
+    else
+        Py_INCREF(builtins);
     assert(builtins);
     RECORD_PUSH_CONSTANT(builtins);
+    Py_DECREF(builtins);
     optimiser->instruction_count++;
     optimiser->fast_frame(optimiser, n, co);
     /* push frame */

Python/register_interpreter.c

         if (tstate->async_exc != NULL) { \
             PyObject *exc; \
             HotPy_RestoreThreadState(tstate, the_context); \
+            Py_DECREF(the_trace); \
             Py_DECREF(trace); \
             exc = tstate->async_exc; \
             tstate->async_exc = NULL; \
             builtins = PyDict_GetItemString(globals, "__builtins__");
             if (PyModule_Check(builtins))
                 builtins = PyObject_GetAttrString(builtins, "__dict__");
+            else
+                Py_INCREF(builtins);
             assert(builtins);
             Py_INCREF(globals);
-            Py_INCREF(builtins);
             SET_REGISTER(r1, globals);
             SET_REGISTER(r2, builtins);
             DISPATCH();
                 e0 = next_instr[-1];
                 PyTuple_SET_ITEM(trace->trace_exits, e0, _HotPy_PolyExit(exit));
                 LOG("Transforming mono-exit to poly-exit");
-                _HotPy_Stats.mono_to_poly++;
+                _HotPy_Stats.mono_to_poly_exit++;
                 HotPy_RestoreThreadState(tstate, exit->exit_context);
                 exit_address = HotPyIP_ToAddr(exit->exit_context->cf_instrs[0]);
                 assert(valid_ip_here(exit_address));
             }
             /* To do -- Upgrade to Poly exit */
             exit = GETEXIT(e0);
+            _HotPy_Stats.rare_exits++;
             goto rare_exit;
 
         TARGET(POLY_EXIT)
             if (gen->gi_frame == NULL ||
                 offset != (unsigned short)gen->gi_frame->f_lasti) {
                 exit = GETEXIT(e0);
+                _HotPy_Stats.rare_exits++;
                 goto rare_exit;
             }
             DISPATCH();
             }
             if (x == NULL) {
                 exit = GETEXIT(e0);
+                _HotPy_Stats.rare_exits++;
                 goto rare_exit;
             }
             SET_REGISTER(r2, x);
             }
             if (x == NULL) {
                 exit = GETEXIT(e0);
+                _HotPy_Stats.rare_exits++;
                 goto rare_exit;
             }
             Py_INCREF(x);
             PyObject *retval = registers[r0];
             Py_INCREF(retval);
             Py_DECREF(trace);
+            _HotPy_Stats.return_exits++;
             return (HotPyReturnValue) { retval, WHY_RETURN};
 
 #if USE_COMPUTED_GOTOS
         tstate->trace_executing--;
         res = HotPyTraceObject_RaiseAtExit(tstate, exit);
         tstate->trace_executing++;
+        _HotPy_Stats.exception_exits++;
         return res;
     }
     _HotPy_Stats.exception_exits++;
             TRANSFER_TO(exit_trace, exit->exit_context);
         }
         else {
+        _HotPy_Stats.polymorphic_cold_exits++;
 #ifdef Py_DEBUG
             char buf[100];
             sprintf(buf, "Poly object = %lx", (long)value);
 materialised:
     assert(tstate->execution_context == NULL);
     Py_DECREF(trace);
+    _HotPy_Stats.materialisation_exits++;
     if (PyErr_Occurred())
         return (HotPyReturnValue){ NULL, WHY_EXCEPTION };
     else

Python/trace_D_O_C.c

     Py_CLEAR(f->code);
     Py_CLEAR(f->globals);
     Py_CLEAR(f->builtins);
+    Py_CLEAR(f->function);
     for (i = 0; i < f->lcount; i++) {
         assert(f->locals[i] == NULL || is_deferred(f->locals[i]));
         Py_CLEAR(f->locals[i]);
         builtins = PyDict_GetItemString(globals, "__builtins__");
         if (PyModule_Check(builtins))
             builtins = PyObject_GetAttrString(builtins, "__dict__");
+        else
+            Py_INCREF(builtins);
         assert(builtins);
     }
     else {
         globals = read_value(code, consts);
         builtins = read_value(code, consts);
+        Py_INCREF(builtins);
     }
     if (allocated) {
         f = *next_frame;
         tstate->recursion_depth++;
     }
     Py_XDECREF(func);
+    Py_DECREF(builtins);
     for (i = 0; i < lcount; i++) {
         PyObject *obj = create_object(tstate, code, consts);
         if (obj) {
             builtins = PyDict_GetItemString(globals, "__builtins__");
             if (PyModule_Check(builtins))
                 builtins = PyObject_GetAttrString(builtins, "__dict__");
+            else
+                Py_INCREF(builtins);
             assert(builtins);
             PUSH(get_constant(opt, globals));
             PUSH(get_constant(opt, builtins));
+            Py_DECREF(builtins);
         }
         else {
             assert(opt->top_frame->function);
             Py_INCREF(tmp);
             f->locals[i] = tmp;
         }
+        w = MAKE_DEFERRED(x, w);
         f->function = w;
         Py_INCREF(co);
         f->code = (PyObject *)co;

Python/trace_interpreter.c

             builtins = PyDict_GetItemString(globals, "__builtins__");
             if (PyModule_Check(builtins))
                 builtins = PyObject_GetAttrString(builtins, "__dict__");
+            else
+                Py_INCREF(builtins);
             assert(builtins);
             Py_INCREF(globals);
-            Py_INCREF(builtins);
+            Py_DECREF(func);
             PUSH(globals);
             PUSH(builtins);
             DISPATCH();
                 next_instr[-3] = POLY_EXIT;
                 PyTuple_SET_ITEM(trace->trace_exits, oparg, _HotPy_PolyExit(exit));
                 LOG("Transforming mono-exit to poly-exit");
-                _HotPy_Stats.mono_to_poly++;
+                _HotPy_Stats.mono_to_poly_exit++;
                 HotPy_RestoreThreadState(tstate, exit->exit_context);
                 next_instr = HotPyIP_ToAddr(exit->exit_context->cf_instrs[0]);
                 assert(valid_ip_here(next_instr));
         tstate->trace_executing--;
         res = HotPyTraceObject_RaiseAtExit(tstate, exit);
         tstate->trace_executing++;
+        _HotPy_Stats.exception_exits++;
         return res;
     }
     _HotPy_Stats.exception_exits++;
             TRANSFER_TO(exit_trace, exit->exit_context);
         }
         else {
+            _HotPy_Stats.polymorphic_cold_exits++;
 #ifdef Py_DEBUG
             char buf[100];
             sprintf(buf, "Poly object = %lx", (long)value);

Python/trace_manager.c

     return ret;
 }
 
+#ifdef Py_DEBUG
+static unsigned long
+total_exits(void)
+{
+    return _HotPy_Stats.not_bool_exits +
+           _HotPy_Stats.return_exits +
+           _HotPy_Stats.rare_exits +
+           _HotPy_Stats.exception_exits +
+           _HotPy_Stats.invalid_exits +
+           _HotPy_Stats.cold_exits +
+           _HotPy_Stats.polymorphic_cold_exits +
+           _HotPy_Stats.polymorphic_overflow_exits +
+           _HotPy_Stats.materialisation_exits +
+           _HotPy_Stats.mono_to_poly_exit;
+}
+#endif
+
 /* Steals a reference to trace */
 HotPyReturnValue
 HotPyTrace_Execute(PyThreadState *tstate, HotPyTraceObject *trace)
     else {
         result = _HotPy_TraceExcecuteCold(tstate, trace, "top-level");
     }
+    assert(total_exits() == _HotPy_Stats.trace_entries);
     tstate->trace_executing--;
     assert(tstate->execution_context == NULL);
     return result;
     assert(trace->status != TRACE_NOT_READY);
     ts->trace_executing--;
     ts->optimiser->clear(ts->optimiser);
+    assert(exit->exit_trace == NULL);
     if (res.why == WHY_EXCEPTION) {
         Py_DECREF(trace);
     } else
         Py_DECREF(context);
         return NULL;
     }
-    assert(context == NULL || Py_TYPE(context) == &Context_Type);
+    assert(Py_TYPE(context) == &Context_Type);
     Py_INCREF(context);
     exit->exit_context = context;
     exit->exit_trace = NULL;
 #endif
     printf("%ld Trace entries\n", _HotPy_Stats.trace_entries);
     printf("%ld Trace transfers\n", _HotPy_Stats.trace_transfers);
-    printf("%ld Transformations of mono-exits to poly-exits\n", _HotPy_Stats.mono_to_poly);
+    printf("%ld Transformations of mono-exits to poly-exits\n", _HotPy_Stats.mono_to_poly_exit);
     printf("%ld Polymorphic cold exits\n", _HotPy_Stats.polymorphic_cold_exits);
     printf("%ld Polymorphic overflow exits\n", _HotPy_Stats.polymorphic_overflow_exits);
     printf("%ld Invalid trace exits\n", _HotPy_Stats.invalid_exits);

Python/trace_recorder_register.c

         write_move(x, from, reg);
     }
     else {
-        write_word_112(x, PICK, reg, depth - opt->stack_items);
+        write_word_112(x, PICK, reg, 1+depth-opt->stack_items);
     }
     CONSISTENT(x);
 }