Commits

Mark Shannon  committed 26600a0 Draft

Make stack-level explicit in SETUP_BLOCK (trace) instructions. Fixes problems when DOC has to materialise blocks

  • Participants
  • Parent commits af124c6

Comments (0)

Files changed (11)

File HotPy/gen_format_code.py

 
 
 formats = [
-    'K', 'kK', 'r', 'rr', 'rrr', 'E', 'rrK',
+    'K', 'kkK', 'r', 'rr', 'rrr', 'E', 'rrK',
     'o', 'oo', 'ro', 'rro', 'rrro', 'oK', 'rK', 'rrk',
     'rKE', 'rKKE', 'roK', 'rroK', 'rok', 'rrkkk',
     'rE', 'rrE', 'rrrE', 'roE', 'rroE', 'rrroE',

File Include/register_macros.h

 #define FORMAT_ID_E 0
 #define FORMAT_ID_K 1
-#define FORMAT_ID_kK 2
+#define FORMAT_ID_kkK 2
 #define FORMAT_ID_o 3
 #define FORMAT_ID_oK 4
 #define FORMAT_ID_oo 5
     k0 = instruction_word >> 16; \
     assert(consistent_format(next_instr[-1] & 255, "K"))
 
-#define FORMAT_kK \
-    int k0, k1; \
+#define FORMAT_kkK \
+    int k0, k1, k2; \
     k0 = (instruction_word >> 8) & 255; \
-    k1 = instruction_word >> 16; \
-    assert(consistent_format(next_instr[-1] & 255, "kK"))
+    k1 = (instruction_word >> 16) & 255; \
+    instruction_word = *next_instr++; \
+    k2 = instruction_word & ((1 << 16)-1); \
+    assert(consistent_format(next_instr[-2] & 255, "kkK"))
 
 #define FORMAT_o \
     int r0; \

File Include/register_write_functions.h

 }
 
 static void
-write_kK(HotPyOptimiser *x, int op, int k0, int k1)
+write_kkK(HotPyOptimiser *x, int op, int k0, int k1, int k2)
 {
     assert(k0 >= 0);
     assert(k1 >= 0);
-    assert(consistent_format(op, "kK"));
-    write_word_112(x, op, k0, k1);
+    assert(k2 >= 0);
+    assert(consistent_format(op, "kkK"));
+    write_word_1111(x, op, k0, k1, 0);
+    write_word_22(x, k2, 0);
 }
 
 static void
 }
 
 void
-print_kK(FILE* out, uint32_t **instr_ptr)
+print_kkK(FILE* out, uint32_t **instr_ptr)
 {
     uint32_t *next_instr = *instr_ptr;
     uint32_t instruction_word = *next_instr++;
     int op = instruction_word & 255;
-    FORMAT_kK;
+    FORMAT_kkK;
     *instr_ptr = next_instr;
-    fprintf(out, "%s k%d K%d\n", _HotPy_Instruction_Names[op], k0, k1);
+    fprintf(out, "%s k%d k%d K%d\n", _HotPy_Instruction_Names[op], k0, k1, k2);
 }
 
 void
 }
 
 static uint32_t *
-defuses_for_kK(uint32_t *next_instr, int *defs, int *uses)
+defuses_for_kkK(uint32_t *next_instr, int *defs, int *uses)
 {
     uint32_t instruction_word = *next_instr++;
-    FORMAT_kK;
+    FORMAT_kkK;
     (void)k0;
     (void)k1;
+    (void)k2;
     *defs++ = -1;
     *uses++ = -1;
     return next_instr;
 }
 
 static uint32_t *
-relabel_uses_kK(uint32_t *next_instr, unsigned char *relabel_table)
+relabel_uses_kkK(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_kK(uint32_t *next_instr, unsigned char *relabel_table)
+relabel_defs_kkK(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 HotPyContext *
-get_exit_context_kK(uint32_t *instr, PyObject *exits)
+get_exit_context_kkK(uint32_t *instr, PyObject *exits)
 {
    return NULL;
 }

File Python/register_interpreter.c

             FAST_DISPATCH();
 
         TARGET(SETUP_BLOCK)
-            FORMAT_kK;
-            PyFrame_BlockSetup(f, k0, k1, STACK_LEVEL());
+            FORMAT_kkK; /* op, level, handler */
+            PyFrame_BlockSetup(f, k0, k2, k1); /* op, handler, level */
             FAST_DISPATCH();
 
         TARGET(SETUP_EXCEPT_HANDLER)
             PUSH(exc);
             FAST_DISPATCH();
 
-        TARGET(SETUP_FOR_ITER)
-            FORMAT_K;
-            assert(STACK_LEVEL() > 0);
-            PyFrame_BlockSetup(f, FOR_ITER, k0, STACK_LEVEL()-1);
-            FAST_DISPATCH();
-
         TARGET(MAKE_FRAME)
             FORMAT_rrro;
             PyObject *args = registers[r0];

File Python/register_opcode_targets.h

 &&_unknown_opcode, /* MAP_ADD */
 &&_unknown_opcode, /* TRACE_LOAD_CONSTANT */
 &&TARGET_PICK,
-&&TARGET_SETUP_FOR_ITER,
+&&_unknown_opcode, /* SETUP_FOR_ITER */
 &&_unknown_opcode, /* JUMP_ABSOLUTE_1 */
 &&_unknown_opcode, /* JUMP_ABSOLUTE_2 */
 &&_unknown_opcode, /* JUMP_ABSOLUTE_3 */

File Python/trace_D_O_C.c

     SHOW_FRAME();
 }
 
+
+static void
+materialise_block(HotPyOptimiser *x, PyTryBlock *b)
+{
+    HotPy_DOC *opt = (HotPy_DOC *)x;
+    assert (opt->top_frame->allocated);
+    if (b->b_type == FOR_ITER)
+        x->next->setup_block(x->next, SETUP_FOR_ITER, b->b_handler, b->b_level);
+    else
+        x->next->setup_block(x->next, b->b_type, b->b_handler, b->b_level);
+}
+
+static void
+materialise_blocks(HotPyOptimiser *x, DeferredFrame *f)
+{
+    int i;
+    for (i = 0; i < f->blockcount; i++) {
+        materialise_block(x, &f->blockstack[i]);
+    }
+    f->blockcount = 0;
+}
+
 static void leave_gen_frame(HotPyOptimiser *x)
 {
     HotPy_DOC *opt = (HotPy_DOC *)x;
     assert (opt->top_frame->allocated);
+    if (opt->top_frame->blockcount) {
+        materialise_blocks(x, opt->top_frame);
+    }
     materialise_stack_top(x, STACK_DEPTH());
     if (opt->top_frame->lasti >= 0)
         x->next->set_lasti(x->next, opt->top_frame->lasti);
     if (op == SETUP_EXCEPT_HANDLER) {
         /* Don't optimise this for now */
         /* XXX -- This could be optimised but it is a bit tricky */
-        int i;
-        for (i = 0; i < f->blockcount; i++) {
-             b = &f->blockstack[i];
-             if (b->b_type == FOR_ITER)
-                 b->b_type = SETUP_FOR_ITER;
-             x->next->setup_block(x->next, b->b_type, b->b_handler, b->b_level);
-        }
-        f->blockcount = 0;
+        materialise_blocks(x, f);
         materialise_stack_top(x, STACK_DEPTH());
         x->next->setup_block(x->next, op, handler, level);
         return;

File Python/trace_interpreter.c

             FAST_DISPATCH();
 
         TARGET_WITH_ARG(SETUP_LOOP)
-            PyFrame_BlockSetup(f, SETUP_LOOP, oparg, STACK_LEVEL());
+            PyFrame_BlockSetup(f, SETUP_LOOP, oparg >> 4, oparg & 15);
             FAST_DISPATCH();
 
         TARGET_WITH_ARG(SETUP_EXCEPT)
-            PyFrame_BlockSetup(f, SETUP_EXCEPT, oparg, STACK_LEVEL());
+            PyFrame_BlockSetup(f, SETUP_EXCEPT, oparg >> 4, oparg & 15);
             FAST_DISPATCH();
 
         TARGET_WITH_ARG(SETUP_FINALLY)
-            PyFrame_BlockSetup(f, SETUP_FINALLY, oparg, STACK_LEVEL());
+            PyFrame_BlockSetup(f, SETUP_FINALLY, oparg >> 4, oparg & 15);
             FAST_DISPATCH();
 
         TARGET(SETUP_EXCEPT_HANDLER)
             FAST_DISPATCH();
 
         TARGET_WITH_ARG(SETUP_FOR_ITER)
-            assert(STACK_LEVEL() > 0);
-            PyFrame_BlockSetup(f, FOR_ITER, oparg, STACK_LEVEL()-1);
+            PyFrame_BlockSetup(f, FOR_ITER, oparg >> 4, oparg & 15);
             FAST_DISPATCH();
 
         TARGET(MAKE_FRAME)

File Python/trace_manager.c

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

File Python/trace_recorder_register.c

     int keys_count;
 } HotPyTraceRecorder;
 
-#define FAILED(opt) do { Py_CLEAR(opt->trace); PyErr_Clear(); return -1; } while(0)
+#define FAILED(opt) do { HotPyTrace_Invalidate((PyObject *)opt->trace); PyErr_Clear(); return -1; } while(0)
 
 static void
 resize_code(HotPyTraceRecorder *opt) {
             fprintf(out, "%s\n", _HotPy_Instruction_Names[op]);
             code++;
             break;
-        case SETUP_FOR_ITER: case DELETE_FAST: case DELETE_DEREF:
+        case DELETE_FAST: case DELETE_DEREF:
             print_K(out, &code);
             break;
         case SETUP_BLOCK:
-            print_kK(out, &code);
+            print_kkK(out, &code);
             break;
         case MAKE_FRAME: case NEW_FRAME: case NEW_CLOSURE: case KW_DICT_MERGE:
             print_rrro(out, &code);
         case POP_BLOCK: case POP_EXCEPT: case SETUP_EXCEPT_HANDLER:
         case STOP_ITERATION_OR_RERAISE: case RERAISE:
         case SAVE_EXC_STATE: case SWAP_EXC_STATE: case RESTORE_CLEAR_EXC_STATE:
-        case SETUP_FOR_ITER: case DELETE_FAST: case DELETE_DEREF:
-        case SETUP_BLOCK: case GET_GLOBAL_AND_BUILTINS:
+        case DELETE_FAST: case DELETE_DEREF:
+        case GET_GLOBAL_AND_BUILTINS:
         case UNARY_NOT: case AS_TUPLE: case MAKE_GENERATOR: case GEN_STARTED:
         case HAS_DICT: case GET_TYPE: case OVERRIDES_GENERIC_GETATTRIBUTE:
         case OVERRIDES_GENERIC_SETATTR: case ALLOCATE: case SIZE:
             out++;
             instr++;
             break;
-        case ONE_ARG: case CALL_CFUNC_0:
+        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 POP_BLOCK: case POP_EXCEPT: case SETUP_EXCEPT_HANDLER:
         case STOP_ITERATION_OR_RERAISE: case RERAISE:
         case SAVE_EXC_STATE: case SWAP_EXC_STATE: case RESTORE_CLEAR_EXC_STATE:
-        case SETUP_FOR_ITER: case DELETE_FAST: case DELETE_DEREF:
-        case SETUP_BLOCK: case GET_GLOBAL_AND_BUILTINS:
+        case DELETE_FAST: case DELETE_DEREF:
+        case GET_GLOBAL_AND_BUILTINS:
         case UNARY_NOT: case AS_TUPLE: case MAKE_GENERATOR: case GEN_STARTED:
         case HAS_DICT: case GET_TYPE: case OVERRIDES_GENERIC_GETATTRIBUTE:
         case OVERRIDES_GENERIC_SETATTR: case ALLOCATE: case SIZE:
             assert(length_via_format_matches(op, 1));
             instr++;
             break;
-        case ONE_ARG: case CALL_CFUNC_0:
+        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:
 
 static int
 start(HotPyOptimiser *x, HotPyTraceObject *trace,
-      PyFrameObject *f, HotPyContext *ctx)
+      PyFrameObject *f, HotPyContext *ctx, char *reason)
 {
     HotPyTraceRecorder *opt = (HotPyTraceRecorder *)x;
     opt->next_inst = 0;
         write_word_112(x, SETUP_EXCEPT_HANDLER, 0, 0);
     }
     else if (op == SETUP_FOR_ITER)
-        write_kK(x, SETUP_BLOCK, FOR_ITER, handler);
+        write_kkK(x, SETUP_BLOCK, FOR_ITER, level, handler);
     else
-        write_kK(x, SETUP_BLOCK, op, handler);
+        write_kkK(x, SETUP_BLOCK, op, level, handler);
     CONSISTENT(x);
 }
 
         defs[0] = -1;
         uses[0] = -1;
         return instr + 1;
-    case SETUP_FOR_ITER: case DELETE_FAST: case DELETE_DEREF:
+    case DELETE_FAST: case DELETE_DEREF:
         return defuses_for_K(instr, defs, uses);
     case SETUP_BLOCK:
-        return defuses_for_kK(instr, defs, uses);
+        return defuses_for_kkK(instr, defs, uses);
     case MAKE_FRAME: case NEW_FRAME: case NEW_CLOSURE: case KW_DICT_MERGE:
         return defuses_for_rrro(instr, defs, uses);
     case GET_GLOBAL_AND_BUILTINS:
     case STOP_ITERATION_OR_RERAISE: case RERAISE:
     case SAVE_EXC_STATE: case SWAP_EXC_STATE: case RESTORE_CLEAR_EXC_STATE:
         return instr + 1;
-    case SETUP_FOR_ITER: case DELETE_FAST: case DELETE_DEREF:
+    case DELETE_FAST: case DELETE_DEREF:
         return relabel_uses_K(instr, relabel_uses_table);
     case SETUP_BLOCK:
-        return relabel_uses_kK(instr, relabel_uses_table);
+        return relabel_uses_kkK(instr, relabel_uses_table);
     case MAKE_FRAME: case NEW_FRAME: case NEW_CLOSURE: case KW_DICT_MERGE:
         return relabel_uses_rrro(instr, relabel_uses_table);
     case GET_GLOBAL_AND_BUILTINS:
     case STOP_ITERATION_OR_RERAISE: case RERAISE:
     case SAVE_EXC_STATE: case SWAP_EXC_STATE: case RESTORE_CLEAR_EXC_STATE:
         return instr + 1;
-    case SETUP_FOR_ITER: case DELETE_FAST: case DELETE_DEREF:
+    case DELETE_FAST: case DELETE_DEREF:
         return relabel_defs_K(instr, relabel_defs_table);
     case SETUP_BLOCK:
-        return relabel_defs_kK(instr, relabel_defs_table);
+        return relabel_defs_kkK(instr, relabel_defs_table);
     case MAKE_FRAME: case NEW_FRAME: case NEW_CLOSURE: case KW_DICT_MERGE:
         return relabel_defs_rrro(instr, relabel_defs_table);
     case GET_GLOBAL_AND_BUILTINS:
     case STOP_ITERATION_OR_RERAISE: case RERAISE:
     case SAVE_EXC_STATE: case SWAP_EXC_STATE: case RESTORE_CLEAR_EXC_STATE:
         return NULL;
-    case SETUP_FOR_ITER: case DELETE_FAST: case DELETE_DEREF:
+    case DELETE_FAST: case DELETE_DEREF:
         return get_exit_context_K(instr, exits);
     case SETUP_BLOCK:
-        return get_exit_context_kK(instr, exits);
+        return get_exit_context_kkK(instr, exits);
     case MAKE_FRAME: case NEW_FRAME: case NEW_CLOSURE: case KW_DICT_MERGE:
         return get_exit_context_rrro(instr, exits);
     case GET_GLOBAL_AND_BUILTINS:

File Python/trace_recorder_stack.c

 
 static int
 start(HotPyOptimiser *x, HotPyTraceObject *trace,
-      PyFrameObject *f, HotPyContext *ctx)
+      PyFrameObject *f, HotPyContext *ctx, char *reason)
 {
     HotPyTraceRecorder *opt = (HotPyTraceRecorder *)x;
     opt->next_byte = 0;
 static void
 setup_block(HotPyOptimiser *x, int op, int handler, int level)
 {
+    HotPyTraceRecorder *opt = (HotPyTraceRecorder *)x;
     if (op == SETUP_EXCEPT_HANDLER) {
         assert(handler == -1);
         opcode(x, op);
-    } else
-        opcode_with_arg(x, op, handler);
+    } else {
+        if (handler >= (1 << 12) || level >= (1 << 4))
+            HotPyTrace_Invalidate((PyObject *)opt->trace);
+        else
+            opcode_with_arg(x, op, (handler << 4) | level);
+    }
 }
 
 HotPyOptimiser *HotPyTraceRecorder_New(void) {

File Python/trace_specialiser.c

     PyObject *v;
     assert(STACK_DEPTH(opt->top_frame) >= 0);
     switch (op) {
-    case SETUP_LOOP: case SETUP_EXCEPT: case SETUP_FINALLY: case SETUP_FOR_ITER:
-        break;
     case LIST_APPEND:
         v = POP();
         DROP();