Commits

Mark Shannon committed 6c14c0b Draft

Fix register interpreter's handling of STORE_MAP, COPY_MOVE and materialisation

Comments (0)

Files changed (3)

Python/register_interpreter.c

 
 typedef uint32_t instruction_t;
 
+#define PUSH_TO_REAL(x) \
+    *tstate->real_frame->f_stacktop++ = (x)
+
 HotPyReturnValue
 _HotPy_TraceRegisterInterpreter(PyThreadState *tstate, HotPyTraceObject *trace)
 {
                 goto error_with_exit;
             }
             if (tstate->execution_context == NULL) {
-                PUSH(x);
+                PUSH_TO_REAL(x);
                 goto materialised;
             }
             SET_REGISTER(r1, x);
             x = ((unaryfunc)wrapped)(arg);
             if (tstate->execution_context == NULL) {
                 if (x)
-                    PUSH(x);
+                    PUSH_TO_REAL(x);
                 goto materialised;
             }
             if (x == NULL) {
             x = ((binaryfunc)wrapped)(arg0, arg1);
             if (tstate->execution_context == NULL) {
                 if (x)
-                    PUSH(x);
+                    PUSH_TO_REAL(x);
                 goto materialised;
             }
             if (x == NULL) {
             x = (*meth)(self, NULL);
             if (tstate->execution_context == NULL) {
                 if (x)
-                    PUSH(x);
+                    PUSH_TO_REAL(x);
                 goto materialised;
             }
             if (x == NULL) {
             x = (*meth)(self, args);
             if (tstate->execution_context == NULL) {
                 if (x)
-                    PUSH(x);
+                    PUSH_TO_REAL(x);
                 goto materialised;
             }
             if (x == NULL) {
             x = (*(PyCFunctionWithKeywords)meth)(self, args, kws);
             if (tstate->execution_context == NULL) {
                 if (x)
-                    PUSH(x);
+                    PUSH_TO_REAL(x);
                 goto materialised;
             }
             if (x == NULL) {
             x = (*meth)(self, NULL);
             if (tstate->execution_context == NULL) {
                 if (x)
-                    PUSH(x);
+                    PUSH_TO_REAL(x);
                 goto materialised;
             }
             if (x == NULL) {
             x = (*meth)(self, args);
             if (tstate->execution_context == NULL) {
                 if (x)
-                    PUSH(x);
+                    PUSH_TO_REAL(x);
                 goto materialised;
             }
             if (x == NULL) {
             x = (*(PyCFunctionWithKeywords)meth)(self, args, kws);
             if (tstate->execution_context == NULL) {
                 if (x)
-                    PUSH(x);
+                    PUSH_TO_REAL(x);
                 goto materialised;
             }
             if (x == NULL) {
                     goto error_with_exit;
             }
             if (tstate->execution_context == NULL) {
-                PUSH(x);
+                PUSH_TO_REAL(x);
                 goto materialised;
             }
             SET_REGISTER(r3, x);

Python/trace_interpreter.c

             DISPATCH();
 
         /* NOTE: The semantics of this are different to ceval.
-         * The arguments are in a different order and this consumes
-         * the dict */
+         * The arguments are in a different order. */
         TARGET(STORE_MAP)
             int err;
             PyObject *w = TOP();     /* dict */

Python/trace_recorder_register.c

 {
     uint32_t *instr = code;
     uint32_t *out = code;
+    uint32_t *end;
     while (instr < code + count) {
         int op = instr[0] & 255;
         switch(op) {
             abort();
         }
     }
+    end = out;
     instr = code;
-    while (instr < out) {
+    out = code;
+    while (instr < end) {
         int op = instr[0] & 255;
         switch(op) {
         case MOVE:
                 uint32_t to1 = (instr[1] >> 16) & 255;
                 assert (from1 != to1);
                 if (to == from1 || to == to1) {
-                    instr[0] = COPY_MOVE | (from << 8) |
+                    out[0] = COPY_MOVE | (from << 8) |
                     (to << 16) | (to1 << 24);
-                    instr++;
+                    instr += 2;
+                    out++;
                     break;
                 }
                 else {
-                    instr[0] = TWO_MOVE | (from << 8) |
+                    out[0] = TWO_MOVE | (from << 8) |
                                (from1 << 16) | (to << 24);
-                    instr[1] = to1;
+                    out[1] = to1;
                     instr += 2;
+                    out += 2;
                     break;
                 }
             }
+            out[0] = instr[0];
             instr++;
+            out++;
             break;
         }
         case LEAVE_FRAME: case POP_CALLER_BLOCK: case CLEAR_FRAME:
         case EXIT_IF_FALSE: case EXIT_IF_TRUE: case EXIT_IF_NOT_BOOL_OR_INT:
         case MATERIALISE_FRAME:
             assert(length_via_format_matches(op, 1));
+            out[0] = instr[0];
+            out++;
             instr++;
             break;
         case ONE_ARG: case CALL_CFUNC_0: case SETUP_BLOCK:
         case STORE_TO_GLOBALS: case SET_IN_OBJECT_DICT_CONST:
         case FAST_LOAD_GLOBAL: case LOAD_SLOT_EX:
             assert(length_via_format_matches(op, 2));
+            out[0] = instr[0];
+            out[1] = instr[1];
+            out += 2;
             instr += 2;
             break;
         default:
     case CLEAR_FRAME: case POP_EXCEPT:
         write_word_112(x, op, 0, 0);
         return;
-    case SET_IN_OBJECT_DICT: case DESCRIPTOR_SET: case STORE_MAP:
+    case SET_IN_OBJECT_DICT: case DESCRIPTOR_SET:
         write_rrr(x, op);
         return;
+    case STORE_MAP:
+        /* STORE_MAP would have rrp format, but that is not allowed. */
+        r0 = peek_as_register(x, 0);
+        write_rrr(x, op);
+        push_register(x, r0);
+        return;
     case GEN_EXIT: case RETURN_VALUE:
         write_r(x, op);
         return;