uops = get_opnames(ex)
# When the result of type(...) is known, _CALL_TYPE_1 is decomposed.
self.assertNotIn("_CALL_TYPE_1", uops)
+ # _CALL_TYPE_1 produces 2 _POP_TOP_NOP (callable and null)
+ # type(42) is int produces 4 _POP_TOP_NOP
+ self.assertGreaterEqual(count_ops(ex, "_POP_TOP_NOP"), 6)
def test_call_type_1_result_is_const(self):
def testfunc(n):
self.assertEqual(res, TIER2_THRESHOLD)
uops = get_opnames(ex)
self.assertNotIn("_LOAD_SPECIAL", uops)
+ # __enter__/__exit__ produce 2 _POP_TOP_NOP
+ # x += 1 produces 2 _POP_TOP_NOP
+ # __exit__()'s None return produces 1 _POP_TOP_NOP
+ self.assertGreaterEqual(count_ops(ex, "_POP_TOP_NOP"), 5)
def test_store_fast_refcount_elimination(self):
def foo(x):
next = sym_new_type(ctx, &PyLong_Type);
}
- op(_CALL_TYPE_1, (unused, unused, arg -- res, a)) {
+ op(_CALL_TYPE_1, (callable, null, arg -- res, a)) {
PyObject* type = (PyObject *)sym_get_type(arg);
if (type) {
res = sym_new_const(ctx, type);
ADD_OP(_SWAP, 3, 0);
- ADD_OP(_POP_TOP, 0, 0);
- ADD_OP(_POP_TOP, 0, 0);
+ optimize_pop_top(ctx, this_instr, callable);
+ optimize_pop_top(ctx, this_instr, null);
ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)type);
ADD_OP(_SWAP, 2, 0);
}
a = arg;
}
- op(_CALL_ISINSTANCE, (unused, unused, instance, cls -- res)) {
+ op(_CALL_ISINSTANCE, (callable, null, instance, cls -- res)) {
// the result is always a bool, but sometimes we can
// narrow it down to True or False
res = sym_new_type(ctx, &PyBool_Type);
out = Py_True;
}
sym_set_const(res, out);
- ADD_OP(_POP_TOP, 0, 0);
- ADD_OP(_POP_TOP, 0, 0);
- ADD_OP(_POP_TOP_NOP, 0, 0);
- ADD_OP(_POP_TOP, 0, 0);
+ optimize_pop_top(ctx, this_instr, cls);
+ optimize_pop_top(ctx, this_instr, instance);
+ optimize_pop_top(ctx, this_instr, null);
+ optimize_pop_top(ctx, this_instr, callable);
ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)out);
}
}
ADD_OP(immortal ? _LOAD_CONST_INLINE_BORROW : _LOAD_CONST_INLINE,
0, (uintptr_t)descr);
ADD_OP(_SWAP, 3, 0);
- ADD_OP(_POP_TOP, 0, 0);
+ optimize_pop_top(ctx, this_instr, method_and_self[0]);
if ((type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) {
PyType_Watch(TYPE_WATCHER_ID, (PyObject *)type);
_Py_BloomFilter_Add(dependencies, type);
ADD_OP(immortal ? _LOAD_CONST_INLINE_BORROW : _LOAD_CONST_INLINE,
0, (uintptr_t)descr);
ADD_OP(_SWAP, 3, 0);
- ADD_OP(_POP_TOP, 0, 0);
+ optimize_pop_top(ctx, this_instr, method_and_self[0]);
if ((type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) {
PyType_Watch(TYPE_WATCHER_ID, (PyObject *)type);
_Py_BloomFilter_Add(dependencies, type);
case _CALL_TYPE_1: {
JitOptRef arg;
+ JitOptRef null;
+ JitOptRef callable;
JitOptRef res;
JitOptRef a;
arg = stack_pointer[-1];
+ null = stack_pointer[-2];
+ callable = stack_pointer[-3];
PyObject* type = (PyObject *)sym_get_type(arg);
if (type) {
res = sym_new_const(ctx, type);
ADD_OP(_SWAP, 3, 0);
- ADD_OP(_POP_TOP, 0, 0);
- ADD_OP(_POP_TOP, 0, 0);
+ optimize_pop_top(ctx, this_instr, callable);
+ optimize_pop_top(ctx, this_instr, null);
ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)type);
ADD_OP(_SWAP, 2, 0);
}
case _CALL_ISINSTANCE: {
JitOptRef cls;
JitOptRef instance;
+ JitOptRef null;
+ JitOptRef callable;
JitOptRef res;
cls = stack_pointer[-1];
instance = stack_pointer[-2];
+ null = stack_pointer[-3];
+ callable = stack_pointer[-4];
res = sym_new_type(ctx, &PyBool_Type);
PyTypeObject *inst_type = sym_get_type(instance);
PyTypeObject *cls_o = (PyTypeObject *)sym_get_const(ctx, cls);
out = Py_True;
}
sym_set_const(res, out);
- ADD_OP(_POP_TOP, 0, 0);
- ADD_OP(_POP_TOP, 0, 0);
- ADD_OP(_POP_TOP_NOP, 0, 0);
- ADD_OP(_POP_TOP, 0, 0);
+ optimize_pop_top(ctx, this_instr, cls);
+ optimize_pop_top(ctx, this_instr, instance);
+ optimize_pop_top(ctx, this_instr, null);
+ optimize_pop_top(ctx, this_instr, callable);
ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)out);
}
CHECK_STACK_BOUNDS(-3);