-
-
Notifications
You must be signed in to change notification settings - Fork 30.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PyCompile_OpcodeStackEffect() and dis.stack_effect() are not particularly useful #76636
Comments
The information provided by PyCompile_OpcodeStackEffect() and dis.stack_effect() (added in bpo-19722) is not enough for practical use.
The possible solution is to add a boolean flag for distinguishing the stack effects in case of consequent execution and jumping. Return a special sentinel or raise an exception if the opcode doesn't pass execution in this direction. |
After resolving bpo-24340 I'm going to add PyCompile_OpcodeStackEffect() that takes an additional integer argument, and add an optional tristate argument to dis.stack_effect(). If it is True, return the effect when jump, if it is false, return the effect when not jump, when omitted or None, return the maximal effect. |
What was the rationale for exposing these interfaces in the first place? If they're not useful, I'd rather deprecate and remove them. |
The rationale: without this information, it is impossible for anybody else to write a bytecode compiler / assembler, because when you create a code object you have to specify its stack depth. I used this information for my "maynard" bytecode assembler / disassembler. That said, I'm not sure who needs these super-fancy versions Serhiy is proposing. To calculate stack depth, all you really need is the *maximum* stack depth per instruction. You might slightly over-allocate but it shouldn't really be much of a problem. Serhiy: what's your use case for all these complicated new features? |
new_depth = depth + PyCompile_OpcodeStackEffectEx(opcode, oparg, 0);
if (new_depth > maxdepth)
maxdepth = new_depth;
if (isjump) {
target_depth = depth + PyCompile_OpcodeStackEffectEx(opcode, oparg, 1);
maxdepth = stackdepth_walk(c, instr->i_target, target_depth, maxdepth);
}
depth = new_depth; After adding new opcodes or changing existing opcodes you would need to change the code only in one place.
|
Simplify whose code, the caller or the callee? It seems like it's simplifying the life of the callee (PyCompile_OpcodeStackEffectEx) at the expense of pushing complexity into the caller.
What complicated code? Compilers simply call PyCompile_OpcodeStackEffect(), passing in an opcode + oparg pair, and it simply returns the maximum stack effect. No crazy "is it a jump" logic needed. Again: this may mean overallocating the stack. But CPython has behaved like this for twenty years and I'm not convinced it's a problem that needs solving. Victor, do you want to use Serhiy's proposed API in your library? |
In 3.7 the stack effect is calculated more accurately by the compiler. PR 6610 exposes this feature to users. It add jump parameter to dis.stack_effect() and to PyCompile_OpcodeStackEffect(). By default the maximal value is returned. Passing jump=True for a non-jumping code or passing jump=False to RETURN_VALUE or JUMP_ABSOLUTE don't raise an exception and don't return a special value. It is up to the caller to pass reliable arguments. This will make the workaround for stack_effect() in the bytecode project [1] not needed in 3.8. |
Sorry if this doesn't fit this issue and needs a separate one. Since Python switched to 2 byte wordcode, all opcodes which do not imply an argument, technically have it - augmented with 0. So it is convenient to iterate over bytecode like: op, arg = instruction. But there is a check in stack_effect that the second argument for this opcodes must be None. file::_opcode.c else if (oparg != Py_None) {
PyErr_SetString(PyExc_ValueError,
"stack_effect: opcode does not permit oparg but oparg was specified");
return -1;
} So you need to perform a somewhat _redundant_ check before calling: arg = arg if op >= opcode.HAVE_ARGUMENT else None.
st = stack_effect(op, arg) Maybe it's normal to relax this condition - be None or 0 for opcode < opcode.HAVE_ARGUMENT? |
I concur with Kirill and was going to propose this change in a separate issue. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: