Mark Shannon avatar Mark Shannon committed b2bf1fb Draft

More fixes to the register allocator

Comments (0)

Files changed (7)

HotPy/gen_format_code.py

         print ('    int r%d = pop_as_register(x, %d);' % (i+peek, i+peek), file = outfile)
     if peek:
         assert fmt.count('p') == 1
-        print ('    int r0 = peek_as_register(x, 0);', file = outfile)
+        print ('    int r0 = peek_as_register(x);', file = outfile)
     for i in range(outputs):
         print ('    int out%d;' % i, file = outfile)
     consts = 0
     'o', 'oo', 'ro', 'rro', 'rrro', 'oK', 'rK', 'rrk',
     'rKE', 'rKKE', 'roK', 'rroK', 'rok', 'rrkkk',
     'rE', 'rrE', 'rroE', 'rrroE', 'rokk', 'rokE',
-    'rokkkE', 'rrok', 'p', 'oKKK',
+    'rokkkE', 'rrok', 'p', 'oKKK', 'rrrE',
     'rrooE', 'rroooE', 'rroo', 'roo',
     'oKE', 'roKE', 'rrKE', 'rroKE', 'rrrKE', 'rrrokE'
 ]

Include/register_macros.h

 #define FORMAT_ID_rrooE 34
 #define FORMAT_ID_rroooE 35
 #define FORMAT_ID_rrr 36
-#define FORMAT_ID_rrrKE 37
-#define FORMAT_ID_rrro 38
-#define FORMAT_ID_rrroE 39
-#define FORMAT_ID_rrrokE 40
+#define FORMAT_ID_rrrE 37
+#define FORMAT_ID_rrrKE 38
+#define FORMAT_ID_rrro 39
+#define FORMAT_ID_rrroE 40
+#define FORMAT_ID_rrrokE 41
 
 #define FORMAT_E \
     int e0; \
     r2 = (instruction_word >> 24); \
     assert(consistent_format(next_instr[-1] & 255, "rrr"))
 
+#define FORMAT_rrrE \
+    int r0, r1, r2, e0; \
+    r0 = (instruction_word >> 8) & 255; \
+    r1 = (instruction_word >> 16) & 255; \
+    r2 = (instruction_word >> 24); \
+    instruction_word = *next_instr++; \
+    e0 = instruction_word & ((1 << 16)-1); \
+    assert(consistent_format(next_instr[-2] & 255, "rrrE"))
+
 #define FORMAT_rrrKE \
     int r0, r1, r2, k0, e0; \
     r0 = (instruction_word >> 8) & 255; \

Include/register_write_functions.h

 static void
 write_p(HotPyOptimiser *x, int op)
 {
-    int r0 = peek_as_register(x, 0);
+    int r0 = peek_as_register(x);
     assert(consistent_format(op, "p"));
     write_word_1111(x, op, r0, 0, 0);
 }
 }
 
 static void
+write_rrrE(HotPyOptimiser *x, int op, int exit)
+{
+    int r2 = pop_as_register(x, 2);
+    int r1 = pop_as_register(x, 1);
+    int r0 = pop_as_register(x, 0);
+    assert(exit >= 0);
+    flush_stack(x);
+    assert(consistent_format(op, "rrrE"));
+    write_word_1111(x, op, r0, r1, r2);
+    write_word_22(x, exit, 0);
+}
+
+static void
 write_rrrKE(HotPyOptimiser *x, int op, int k0, int exit)
 {
     int r2 = pop_as_register(x, 2);
 }
 
 void
+print_rrrE(FILE* out, uint32_t **instr_ptr)
+{
+    uint32_t *next_instr = *instr_ptr;
+    uint32_t instruction_word = *next_instr++;
+    int op = instruction_word & 255;
+    FORMAT_rrrE;
+    *instr_ptr = next_instr;
+    fprintf(out, "%s r%d r%d r%d exit%d\n", _HotPy_Instruction_Names[op], r0, r1, r2, e0);
+}
+
+void
 print_rrrKE(FILE* out, uint32_t **instr_ptr)
 {
     uint32_t *next_instr = *instr_ptr;
 }
 
 static uint32_t *
+defuses_for_rrrE(uint32_t *next_instr, int *defs, int *uses)
+{
+    uint32_t instruction_word = *next_instr++;
+    FORMAT_rrrE;
+    *uses++ = r0;
+    *uses++ = r1;
+    *uses++ = r2;
+    (void)e0;
+    *defs++ = -1;
+    *uses++ = -1;
+    return next_instr;
+}
+
+static uint32_t *
 defuses_for_rrrKE(uint32_t *next_instr, int *defs, int *uses)
 {
     uint32_t instruction_word = *next_instr++;
 }
 
 static uint32_t *
+relabel_uses_rrrE(uint32_t *next_instr, unsigned char *relabel_table)
+{
+    int reg;
+    uint32_t instruction_word = *next_instr++;
+    (void)instruction_word; /* Stop compiler complaining */
+    reg = (instruction_word >> 8) & 255; \
+    instruction_word = (instruction_word & 0xffff00ff) | (relabel_table[reg] << 8);
+    reg = (instruction_word >> 16) & 255; \
+    instruction_word = (instruction_word & 0xff00ffff) | (relabel_table[reg] << 16);
+    reg = (instruction_word >> 24); \
+    instruction_word = (instruction_word & 0x00ffffff) | (relabel_table[reg] << 24);
+    next_instr[-1] = instruction_word;
+    instruction_word = *next_instr++;
+    next_instr[-1] = instruction_word;
+    return next_instr;
+}
+
+static uint32_t *
 relabel_uses_rrrKE(uint32_t *next_instr, unsigned char *relabel_table)
 {
     int reg;
 }
 
 static uint32_t *
+relabel_defs_rrrE(uint32_t *next_instr, unsigned char *relabel_table)
+{
+    uint32_t instruction_word = *next_instr++;
+    (void)instruction_word; /* Stop compiler complaining */
+    next_instr[-1] = instruction_word;
+    instruction_word = *next_instr++;
+    next_instr[-1] = instruction_word;
+    return next_instr;
+}
+
+static uint32_t *
 relabel_defs_rrrKE(uint32_t *next_instr, unsigned char *relabel_table)
 {
     uint32_t instruction_word = *next_instr++;
 }
 
 static HotPyContext *
+get_exit_context_rrrE(uint32_t *instr, PyObject *exits)
+{
+    uint32_t instruction_word = *instr++;
+    int e0;
+    PyObject *exit;
+    instruction_word = *instr++;
+    e0 = instruction_word & ((1 << 16)-1); \
+    exit = PyTuple_GetItem(exits, e0);
+    return ((HotPyExitObject *)exit)->exit_context;
+}
+
+static HotPyContext *
 get_exit_context_rrrKE(uint32_t *instr, PyObject *exits)
 {
     uint32_t instruction_word = *instr++;

Python/register_interpreter.c

         TARGET(STORE_MAP)
             FORMAT_rrr;
             int err;
-            PyObject *w = registers[r2];   /* value */
+            PyObject *w = registers[r2];   /* dict */
             PyObject *u = registers[r1];   /* key */
-            PyObject *v = registers[r0];   /* dict */
+            PyObject *v = registers[r0];   /* value */
             assert (PyDict_CheckExact(w));
             err = PyDict_SetItem(w, u, v);  /* w[u] = v */
             if (err == 0)
             DISPATCH();
 
         TARGET(TRACE_DESCRIPTOR_GET)
+            FORMAT_rroE;
+            PyObject *v = registers[r0];
+            PyObject *w = registers[r1];
+            exit = GETEXIT(e0);
+            tstate->execution_context = exit->exit_context;
+            PyObject *x = Py_TYPE(v)->tp_descr_get(v, w, (PyObject *)Py_TYPE(w));
+            if (tstate->execution_context == NULL) {
+                if (x)
+                    PUSH_TO_REAL(x);
+                goto materialised;
+            }
+            if (x == NULL)
+                goto error_with_exit;
+            SET_REGISTER(r2, x);
+            tstate->execution_context = NULL;
+            DISPATCH();
+
+        TARGET(DESCRIPTOR_GET)
             FORMAT_rro;
             PyObject *v = registers[r0];
             PyObject *w = registers[r1];
             DISPATCH();
 
         TARGET(TRACE_DESCRIPTOR_SET)
-            FORMAT_rrr;
+            FORMAT_rrrE;
             PyObject *v = registers[r0];
             PyObject *w = registers[r1];
             PyObject *u = registers[r2];
-            int err = Py_TYPE(v)->tp_descr_set(v, w, u);
-            if (err == 0) DISPATCH();
-            goto on_error;
+            int err;
+            exit = GETEXIT(e0);
+            tstate->execution_context = exit->exit_context;
+            err = Py_TYPE(v)->tp_descr_set(v, w, u);
+            if (tstate->execution_context == NULL)
+                goto materialised;
+            if (err)
+                goto error_with_exit;
+            tstate->execution_context = NULL;
+            DISPATCH();
 
         TARGET(GET_CLASS_ATTR)
             FORMAT_rro;

Python/register_opcode_targets.h

 &&TARGET_OVERRIDES,
 &&TARGET_GEN_CLEAR,
 &&TARGET_OVERRIDES_GENERIC_SETATTR,
-&&_unknown_opcode, /* DESCRIPTOR_GET */
+&&TARGET_DESCRIPTOR_GET,
 &&_unknown_opcode, /* DESCRIPTOR_SET */
 &&_unknown_opcode, /* TRACE_END */
 &&TARGET_GET_GLOBAL_AND_BUILTINS,

Python/trace_manager.c

      /* Turn these off by default for now */
     _HotPy_Options.specialise = option(xopts, "specialise", 1);
     _HotPy_Options.DOC = option(xopts, "defer", 1);
-    _HotPy_Options.register_vm = option(xopts, "register", 0);
+    _HotPy_Options.register_vm = option(xopts, "register", 1);
     _HotPy_Options.coalesce = option(xopts, "coalesce", 0);
     _HotPy_Options.tailcall = option(xopts, "tailcall", 0);
     decay = PyDict_GetItemString(xopts, "decay_interval");

Python/trace_recorder_register.c

         if (opt->used_regs[i] == 0)
             return 0;
     }
-    for (i = 4; i < HOTPY_STACK_REGISTERS; i++)
+    for (i = 0; i < HOTPY_STACK_REGISTERS; i++)
         used += opt->used_regs[i];
     return used == opt->stack_items;
 }
 {
     int i, chosen;
     HotPyTraceRecorder *opt = (HotPyTraceRecorder *)x;
-    for (i = 4; i < HOTPY_STACK_REGISTERS; i++) {
+    for (i = 0; i < HOTPY_STACK_REGISTERS; i++) {
         if (opt->used_regs[i] == 0) {
             opt->used_regs[i] = 1;
             return i;
     opt->stack[opt->stack_items++] = reg;
 }
 
-static int peek_as_register(HotPyOptimiser *x, int def)
+static int peek_as_register(HotPyOptimiser *x)
 {
+    int reg;
     HotPyTraceRecorder *opt = (HotPyTraceRecorder *)x;
     if (opt->stack_items)
         return opt->stack[opt->stack_items-1];
-    write_word_1111(x, POP_STACK_TO_REGISTER, def, 0, 0);
-    write_word_1111(x, PUSH_REGISTER_TO_STACK, def, 0, 0);
-    return def;
+    reg = choose_register(x);
+    write_word_1111(x, POP_STACK_TO_REGISTER, reg, 0, 0);
+    push_register(x, reg);
+    return reg;
 }
 
 #include "register_write_functions.h"
         case VALUE_FROM_OBJECT_DICT_OR_EXIT:
             print_rroE(out, &code);
             break;
-        case ONE_ARG:
+        case ONE_ARG: case TRACE_DESCRIPTOR_GET:
             print_rroE(out, &code);
             break;
         case CALL_CFUNC_0:
     case VALUE_FROM_OBJECT_DICT_OR_EXIT: case CALL_CFUNC_1: case CALL_CMETH_0:
         write_rroE(x, op, index);
         break;
-    case ONE_ARG:
+    case ONE_ARG: case TRACE_DESCRIPTOR_GET:
         write_rroE(x, op, index);
         break;
     case NO_ARGS:
         case ONE_ARG: case CALL_CFUNC_0: case SETUP_BLOCK:
         case CALL_CFUNC_2: case CALL_CMETH_1: case CALL_CMETH_2:
         case CALL_WRAPPER_BINARY: case CALL_OBJECT:
-        case CALL_WRAPPER_TRINARY_PROC:
+        case CALL_WRAPPER_TRINARY_PROC: case TRACE_DESCRIPTOR_GET:
         case CALL_WRAPPER_BINARY_NULL_PROC: case NO_ARGS:
         case EXIT_IF_VALUE_IN_OBJECT_DICT: case NO_KEYWORDS:
         case ONE_PLUS_ARGS: case TWO_ARGS: case THREE_ARGS:
         case ONE_ARG: case CALL_CFUNC_0: case SETUP_BLOCK:
         case CALL_CFUNC_2: case CALL_CMETH_1: case CALL_CMETH_2:
         case CALL_WRAPPER_BINARY: case CALL_OBJECT:
-        case CALL_WRAPPER_TRINARY_PROC:
+        case CALL_WRAPPER_TRINARY_PROC: case TRACE_DESCRIPTOR_GET:
         case CALL_WRAPPER_BINARY_NULL_PROC: case NO_ARGS:
         case EXIT_IF_VALUE_IN_OBJECT_DICT: case NO_KEYWORDS:
         case ONE_PLUS_ARGS: case TWO_ARGS: case THREE_ARGS:
         opt->stack[opt->stack_items-1] = r1;
         return;
     case DUP_TOP:
-        r0 = peek_as_register(x, 0);
+        r0 = peek_as_register(x);
         r1 = choose_register(x);
         write_move(x, r0, r1);
         push_register(x, r1);
         return;
     case STORE_MAP:
         /* STORE_MAP would have rrp format, but that is not allowed. */
-        r0 = peek_as_register(x, 0);
+        r0 = peek_as_register(x);
         write_rrr(x, op);
-        push_register(x, r0);
+        r1 = choose_register(x);
+        write_move(x, r0, r1);
+        push_register(x, r1);
         return;
     case GEN_EXIT: case RETURN_VALUE:
         write_r(x, op);
         write_rokE(x, LOAD_SLOT_EX, slot, e);
     }
     else {
-        /* Don't support int/float slots yet */
+        assert("Don't support int/float slots yet" && 0);
         abort();
     }
     CONSISTENT(x);
     assert(slot < (1 << 8));
     assert(def->offset % sizeof(PyObject*) == 0);
     assert((def->flags & READONLY) == 0);
-    assert("TO DO -- exit" && 0);
     if (def->type == T_OBJECT || def->type == T_OBJECT_EX) {
         write_rrk(x, STORE_SLOT, slot);
     }
         return defuses_for_roKE(instr, defs, uses);
     case VALUE_FROM_OBJECT_DICT_OR_EXIT:
         return defuses_for_rroE(instr, defs, uses);
-    case ONE_ARG:
+    case ONE_ARG: case TRACE_DESCRIPTOR_GET:
         return defuses_for_rroE(instr, defs, uses);
     case CALL_CFUNC_0:
         return defuses_for_oKE(instr, defs, uses);
         return relabel_uses_roKE(instr, relabel_uses_table);
     case VALUE_FROM_OBJECT_DICT_OR_EXIT:
         return relabel_uses_rroE(instr, relabel_uses_table);
-    case ONE_ARG:
+    case ONE_ARG: case TRACE_DESCRIPTOR_GET:
         return relabel_uses_rroE(instr, relabel_uses_table);
     case CALL_CFUNC_0:
         return relabel_uses_oKE(instr, relabel_uses_table);
         return relabel_defs_roKE(instr, relabel_defs_table);
     case VALUE_FROM_OBJECT_DICT_OR_EXIT:
         return relabel_defs_rroE(instr, relabel_defs_table);
-    case ONE_ARG:
+    case ONE_ARG: case TRACE_DESCRIPTOR_GET:
         return relabel_defs_rroE(instr, relabel_defs_table);
     case CALL_CFUNC_0:
         return relabel_defs_oKE(instr, relabel_defs_table);
         return get_exit_context_roKE(instr, exits);
     case VALUE_FROM_OBJECT_DICT_OR_EXIT:
         return get_exit_context_rroE(instr, exits);
-    case ONE_ARG:
+    case ONE_ARG: case TRACE_DESCRIPTOR_GET:
         return get_exit_context_rroE(instr, exits);
     case CALL_CFUNC_0:
         return get_exit_context_oKE(instr, exits);
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.