#define _STORE_ATTR_SLOT 348
#define _SPECIALIZE_COMPARE_OP 349
#define _COMPARE_OP 350
-#define _IS_NONE 351
-#define _SPECIALIZE_FOR_ITER 352
-#define _FOR_ITER 353
-#define _ITER_CHECK_LIST 354
-#define _ITER_JUMP_LIST 355
-#define _GUARD_NOT_EXHAUSTED_LIST 356
-#define _ITER_NEXT_LIST 357
-#define _ITER_CHECK_TUPLE 358
-#define _ITER_JUMP_TUPLE 359
-#define _GUARD_NOT_EXHAUSTED_TUPLE 360
-#define _ITER_NEXT_TUPLE 361
-#define _ITER_CHECK_RANGE 362
-#define _ITER_JUMP_RANGE 363
-#define _GUARD_NOT_EXHAUSTED_RANGE 364
-#define _ITER_NEXT_RANGE 365
-#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 366
-#define _GUARD_KEYS_VERSION 367
-#define _LOAD_ATTR_METHOD_WITH_VALUES 368
-#define _LOAD_ATTR_METHOD_NO_DICT 369
-#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 370
-#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 371
-#define _CHECK_ATTR_METHOD_LAZY_DICT 372
-#define _LOAD_ATTR_METHOD_LAZY_DICT 373
-#define _SPECIALIZE_CALL 374
-#define _CALL 375
-#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS 376
-#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 377
-#define _CHECK_PEP_523 378
-#define _CHECK_FUNCTION_EXACT_ARGS 379
-#define _CHECK_STACK_SPACE 380
-#define _INIT_CALL_PY_EXACT_ARGS 381
-#define _PUSH_FRAME 382
-#define _SPECIALIZE_BINARY_OP 383
-#define _BINARY_OP 384
-#define _POP_JUMP_IF_FALSE 385
-#define _POP_JUMP_IF_TRUE 386
-#define _JUMP_TO_TOP 387
-#define _SAVE_RETURN_OFFSET 388
-#define _INSERT 389
-#define _CHECK_VALIDITY 390
+#define _POP_JUMP_IF_FALSE 351
+#define _POP_JUMP_IF_TRUE 352
+#define _IS_NONE 353
+#define _SPECIALIZE_FOR_ITER 354
+#define _FOR_ITER 355
+#define _ITER_CHECK_LIST 356
+#define _ITER_JUMP_LIST 357
+#define _GUARD_NOT_EXHAUSTED_LIST 358
+#define _ITER_NEXT_LIST 359
+#define _ITER_CHECK_TUPLE 360
+#define _ITER_JUMP_TUPLE 361
+#define _GUARD_NOT_EXHAUSTED_TUPLE 362
+#define _ITER_NEXT_TUPLE 363
+#define _ITER_CHECK_RANGE 364
+#define _ITER_JUMP_RANGE 365
+#define _GUARD_NOT_EXHAUSTED_RANGE 366
+#define _ITER_NEXT_RANGE 367
+#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 368
+#define _GUARD_KEYS_VERSION 369
+#define _LOAD_ATTR_METHOD_WITH_VALUES 370
+#define _LOAD_ATTR_METHOD_NO_DICT 371
+#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 372
+#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 373
+#define _CHECK_ATTR_METHOD_LAZY_DICT 374
+#define _LOAD_ATTR_METHOD_LAZY_DICT 375
+#define _SPECIALIZE_CALL 376
+#define _CALL 377
+#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS 378
+#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 379
+#define _CHECK_PEP_523 380
+#define _CHECK_FUNCTION_EXACT_ARGS 381
+#define _CHECK_STACK_SPACE 382
+#define _INIT_CALL_PY_EXACT_ARGS 383
+#define _PUSH_FRAME 384
+#define _SPECIALIZE_BINARY_OP 385
+#define _BINARY_OP 386
+#define _GUARD_IS_TRUE_POP 387
+#define _GUARD_IS_FALSE_POP 388
+#define _GUARD_IS_NONE_POP 389
+#define _GUARD_IS_NOT_NONE_POP 390
+#define _JUMP_TO_TOP 391
+#define _SAVE_RETURN_OFFSET 392
+#define _INSERT 393
+#define _CHECK_VALIDITY 394
extern int _PyOpcode_num_popped(int opcode, int oparg, bool jump);
#ifdef NEED_OPCODE_METADATA
return 0;
case ENTER_EXECUTOR:
return 0;
- case POP_JUMP_IF_FALSE:
+ case _POP_JUMP_IF_FALSE:
return 1;
- case POP_JUMP_IF_TRUE:
+ case _POP_JUMP_IF_TRUE:
return 1;
case _IS_NONE:
return 1;
+ case POP_JUMP_IF_TRUE:
+ return 1;
+ case POP_JUMP_IF_FALSE:
+ return 1;
case POP_JUMP_IF_NONE:
return 1;
case POP_JUMP_IF_NOT_NONE:
return 0;
case RESERVED:
return 0;
- case _POP_JUMP_IF_FALSE:
+ case _GUARD_IS_TRUE_POP:
return 1;
- case _POP_JUMP_IF_TRUE:
+ case _GUARD_IS_FALSE_POP:
+ return 1;
+ case _GUARD_IS_NONE_POP:
+ return 1;
+ case _GUARD_IS_NOT_NONE_POP:
return 1;
case _JUMP_TO_TOP:
return 0;
return 0;
case ENTER_EXECUTOR:
return 0;
- case POP_JUMP_IF_FALSE:
+ case _POP_JUMP_IF_FALSE:
return 0;
- case POP_JUMP_IF_TRUE:
+ case _POP_JUMP_IF_TRUE:
return 0;
case _IS_NONE:
return 1;
+ case POP_JUMP_IF_TRUE:
+ return 0;
+ case POP_JUMP_IF_FALSE:
+ return 0;
case POP_JUMP_IF_NONE:
return 0;
case POP_JUMP_IF_NOT_NONE:
return 0;
case RESERVED:
return 0;
- case _POP_JUMP_IF_FALSE:
+ case _GUARD_IS_TRUE_POP:
return 0;
- case _POP_JUMP_IF_TRUE:
+ case _GUARD_IS_FALSE_POP:
+ return 0;
+ case _GUARD_IS_NONE_POP:
+ return 0;
+ case _GUARD_IS_NOT_NONE_POP:
return 0;
case _JUMP_TO_TOP:
return 0;
[JUMP] = { true, 0, HAS_ARG_FLAG | HAS_JUMP_FLAG },
[JUMP_NO_INTERRUPT] = { true, 0, HAS_ARG_FLAG | HAS_JUMP_FLAG },
[ENTER_EXECUTOR] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
- [POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ESCAPES_FLAG },
- [POP_JUMP_IF_TRUE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ESCAPES_FLAG },
+ [_POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ESCAPES_FLAG },
+ [_POP_JUMP_IF_TRUE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ESCAPES_FLAG },
[_IS_NONE] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG },
+ [POP_JUMP_IF_TRUE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ESCAPES_FLAG },
+ [POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ESCAPES_FLAG },
[POP_JUMP_IF_NONE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ESCAPES_FLAG },
[POP_JUMP_IF_NOT_NONE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ESCAPES_FLAG },
[JUMP_BACKWARD_NO_INTERRUPT] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG },
[EXTENDED_ARG] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
[CACHE] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG },
[RESERVED] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG },
- [_POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ESCAPES_FLAG },
- [_POP_JUMP_IF_TRUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ESCAPES_FLAG },
+ [_GUARD_IS_TRUE_POP] = { true, INSTR_FMT_IX, HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG },
+ [_GUARD_IS_FALSE_POP] = { true, INSTR_FMT_IX, HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG },
+ [_GUARD_IS_NONE_POP] = { true, INSTR_FMT_IX, HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG },
+ [_GUARD_IS_NOT_NONE_POP] = { true, INSTR_FMT_IX, HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG },
[_JUMP_TO_TOP] = { true, INSTR_FMT_IX, HAS_EVAL_BREAK_FLAG },
[_SET_IP] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ESCAPES_FLAG },
[_SAVE_RETURN_OFFSET] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
[CONTAINS_OP] = { .nuops = 1, .uops = { { CONTAINS_OP, 0, 0 } } },
[CHECK_EG_MATCH] = { .nuops = 1, .uops = { { CHECK_EG_MATCH, 0, 0 } } },
[CHECK_EXC_MATCH] = { .nuops = 1, .uops = { { CHECK_EXC_MATCH, 0, 0 } } },
+ [POP_JUMP_IF_TRUE] = { .nuops = 1, .uops = { { _POP_JUMP_IF_TRUE, 0, 0 } } },
+ [POP_JUMP_IF_FALSE] = { .nuops = 1, .uops = { { _POP_JUMP_IF_FALSE, 0, 0 } } },
+ [POP_JUMP_IF_NONE] = { .nuops = 2, .uops = { { _IS_NONE, 0, 0 }, { _POP_JUMP_IF_TRUE, 0, 0 } } },
+ [POP_JUMP_IF_NOT_NONE] = { .nuops = 2, .uops = { { _IS_NONE, 0, 0 }, { _POP_JUMP_IF_FALSE, 0, 0 } } },
[GET_LEN] = { .nuops = 1, .uops = { { GET_LEN, 0, 0 } } },
[MATCH_CLASS] = { .nuops = 1, .uops = { { MATCH_CLASS, 0, 0 } } },
[MATCH_MAPPING] = { .nuops = 1, .uops = { { MATCH_MAPPING, 0, 0 } } },
[_STORE_ATTR_SLOT] = "_STORE_ATTR_SLOT",
[_SPECIALIZE_COMPARE_OP] = "_SPECIALIZE_COMPARE_OP",
[_COMPARE_OP] = "_COMPARE_OP",
+ [_POP_JUMP_IF_FALSE] = "_POP_JUMP_IF_FALSE",
+ [_POP_JUMP_IF_TRUE] = "_POP_JUMP_IF_TRUE",
[_IS_NONE] = "_IS_NONE",
[_SPECIALIZE_FOR_ITER] = "_SPECIALIZE_FOR_ITER",
[_FOR_ITER] = "_FOR_ITER",
[_PUSH_FRAME] = "_PUSH_FRAME",
[_SPECIALIZE_BINARY_OP] = "_SPECIALIZE_BINARY_OP",
[_BINARY_OP] = "_BINARY_OP",
- [_POP_JUMP_IF_FALSE] = "_POP_JUMP_IF_FALSE",
- [_POP_JUMP_IF_TRUE] = "_POP_JUMP_IF_TRUE",
+ [_GUARD_IS_TRUE_POP] = "_GUARD_IS_TRUE_POP",
+ [_GUARD_IS_FALSE_POP] = "_GUARD_IS_FALSE_POP",
+ [_GUARD_IS_NONE_POP] = "_GUARD_IS_NONE_POP",
+ [_GUARD_IS_NOT_NONE_POP] = "_GUARD_IS_NOT_NONE_POP",
[_JUMP_TO_TOP] = "_JUMP_TO_TOP",
[_SAVE_RETURN_OFFSET] = "_SAVE_RETURN_OFFSET",
[_INSERT] = "_INSERT",
[LOAD_ATTR] = 9,
[COMPARE_OP] = 1,
[JUMP_BACKWARD] = 1,
- [POP_JUMP_IF_FALSE] = 1,
[POP_JUMP_IF_TRUE] = 1,
+ [POP_JUMP_IF_FALSE] = 1,
[POP_JUMP_IF_NONE] = 1,
[POP_JUMP_IF_NOT_NONE] = 1,
[FOR_ITER] = 1,
.tp_methods = executor_methods,
};
-/* TO DO -- Generate this table */
+/* TO DO -- Generate these tables */
static const uint16_t
_PyUop_Replacements[OPCODE_METADATA_SIZE] = {
[_ITER_JUMP_RANGE] = _GUARD_NOT_EXHAUSTED_RANGE,
[_ITER_JUMP_TUPLE] = _GUARD_NOT_EXHAUSTED_TUPLE,
};
+static const uint16_t
+BRANCH_TO_GUARD[4][2] = {
+ [POP_JUMP_IF_FALSE - POP_JUMP_IF_FALSE][0] = _GUARD_IS_TRUE_POP,
+ [POP_JUMP_IF_FALSE - POP_JUMP_IF_FALSE][1] = _GUARD_IS_FALSE_POP,
+ [POP_JUMP_IF_TRUE - POP_JUMP_IF_FALSE][0] = _GUARD_IS_FALSE_POP,
+ [POP_JUMP_IF_TRUE - POP_JUMP_IF_FALSE][1] = _GUARD_IS_TRUE_POP,
+ [POP_JUMP_IF_NONE - POP_JUMP_IF_FALSE][0] = _GUARD_IS_NOT_NONE_POP,
+ [POP_JUMP_IF_NONE - POP_JUMP_IF_FALSE][1] = _GUARD_IS_NONE_POP,
+ [POP_JUMP_IF_NOT_NONE - POP_JUMP_IF_FALSE][0] = _GUARD_IS_NONE_POP,
+ [POP_JUMP_IF_NOT_NONE - POP_JUMP_IF_FALSE][1] = _GUARD_IS_NOT_NONE_POP,
+};
+
#define TRACE_STACK_SIZE 5
/* Returns 1 on success,
}
switch (opcode) {
-
case POP_JUMP_IF_NONE:
- {
- RESERVE(2, 2);
- ADD_TO_TRACE(_IS_NONE, 0, 0);
- opcode = POP_JUMP_IF_TRUE;
- goto pop_jump_if_bool;
- }
-
case POP_JUMP_IF_NOT_NONE:
- {
- RESERVE(2, 2);
- ADD_TO_TRACE(_IS_NONE, 0, 0);
- opcode = POP_JUMP_IF_FALSE;
- goto pop_jump_if_bool;
- }
-
case POP_JUMP_IF_FALSE:
case POP_JUMP_IF_TRUE:
{
-pop_jump_if_bool:
- RESERVE(1, 2);
- max_length -= 2; // Really the start of the stubs
+ RESERVE(1, 0);
int counter = instr[1].cache;
int bitcount = _Py_popcount32(counter);
- bool jump_likely = bitcount > 8;
- bool jump_sense = opcode == POP_JUMP_IF_TRUE;
- uint32_t uopcode = jump_sense ^ jump_likely ?
- _POP_JUMP_IF_TRUE : _POP_JUMP_IF_FALSE;
+ int jump_likely = bitcount > 8;
+ uint32_t uopcode = BRANCH_TO_GUARD[opcode - POP_JUMP_IF_FALSE][jump_likely];
_Py_CODEUNIT *next_instr = instr + 1 + _PyOpcode_Caches[_PyOpcode_Deopt[opcode]];
- _Py_CODEUNIT *target_instr = next_instr + oparg;
- _Py_CODEUNIT *stub_target = jump_likely ? next_instr : target_instr;
- DPRINTF(4, "%s(%d): counter=%x, bitcount=%d, likely=%d, sense=%d, uopcode=%s\n",
+ DPRINTF(4, "%s(%d): counter=%x, bitcount=%d, likely=%d, uopcode=%s\n",
uop_name(opcode), oparg,
- counter, bitcount, jump_likely, jump_sense, uop_name(uopcode));
+ counter, bitcount, jump_likely, uop_name(uopcode));
ADD_TO_TRACE(uopcode, max_length, 0);
- ADD_TO_STUB(max_length, _SET_IP, INSTR_IP(stub_target, code), 0);
- ADD_TO_STUB(max_length + 1, _EXIT_TRACE, 0, 0);
if (jump_likely) {
+ _Py_CODEUNIT *target_instr = next_instr + oparg;
DPRINTF(2, "Jump likely (%x = %d bits), continue at byte offset %d\n",
instr[1].cache, bitcount, 2 * INSTR_IP(target_instr, code));
instr = target_instr;
}
/* All other micro-ops fall through, so i+1 is reachable */
SET_BIT(used, i+1);
- switch(opcode) {
- case NOP:
- /* Don't count NOPs as used */
- count--;
- UNSET_BIT(used, i);
- break;
- case _POP_JUMP_IF_FALSE:
- case _POP_JUMP_IF_TRUE:
- /* Mark target as reachable */
- SET_BIT(used, buffer[i].oparg);
+ if (OPCODE_HAS_JUMP(opcode)) {
+ /* Mark target as reachable */
+ SET_BIT(used, buffer[i].oparg);
+ }
+ if (opcode == NOP) {
+ count--;
+ UNSET_BIT(used, i);
}
}
return count;