Skip to content

Commit 1461ebc

Browse files
authored
Add LOAD_CONST_R . Fix two bugs: _PyFrame_PushUnchecked does not copy consts, deepfreeze calculates wrong framesize.
1 parent 3ee9a3c commit 1461ebc

File tree

11 files changed

+91
-48
lines changed

11 files changed

+91
-48
lines changed

Include/internal/pycore_frame.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,13 @@ _PyFrame_PushUnchecked(PyThreadState *tstate, PyFunctionObject *func)
220220
tstate->datastack_top += code->co_framesize;
221221
assert(tstate->datastack_top < tstate->datastack_limit);
222222
_PyFrame_InitializeSpecials(new_frame, func, NULL, code);
223+
int nconsts = (int)PyTuple_Size(code->co_consts);
224+
if (nconsts > 0) {
225+
PyObject **const_regs = new_frame->localsplus + (code->co_nlocalsplus +
226+
code->co_stacksize);
227+
PyObject **consts = &PyTuple_GET_ITEM(code->co_consts, 0);
228+
memcpy(const_regs, consts, sizeof(PyObject*) * nconsts);
229+
}
223230
return new_frame;
224231
}
225232

Include/internal/pycore_opcode.h

Lines changed: 8 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/opcode.h

Lines changed: 21 additions & 19 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/importlib/_bootstrap_external.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ def _write_atomic(path, data, mode=0o666):
438438
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
439439
# in PC/launcher.c must also be updated.
440440

441-
MAGIC_NUMBER = (3569).to_bytes(2, 'little') + b'\r\n'
441+
MAGIC_NUMBER = (3572).to_bytes(2, 'little') + b'\r\n'
442442

443443
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
444444

Lib/opcode.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,8 @@ def pseudo_op(name, op, real_ops):
162162
jrel_op('JUMP_FORWARD', 110) # Number of words to skip
163163
jrel_op('JUMP_IF_FALSE_OR_POP', 111) # Number of words to skip
164164
jrel_op('JUMP_IF_TRUE_OR_POP', 112) # ""
165+
def_op('LOAD_CONST_R', 113) # Index in const list
166+
hasconst.append(113)
165167
jrel_op('POP_JUMP_IF_FALSE', 114)
166168
jrel_op('POP_JUMP_IF_TRUE', 115)
167169
name_op('LOAD_GLOBAL', 116) # Index in name list

Python/bytecodes.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,11 @@ dummy_func(
156156
Py_INCREF(value);
157157
}
158158

159+
inst(LOAD_CONST_R, (-- value)) {
160+
value = REG(oparg1);
161+
Py_INCREF(value);
162+
}
163+
159164
inst(STORE_FAST, (value --)) {
160165
SETLOCAL(oparg, value);
161166
}

Python/ceval.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2015,7 +2015,7 @@ _PyEvalFramePushAndInit(PyThreadState *tstate, PyFunctionObject *func,
20152015
PyObject **const_regs = localsarray + (code->co_nlocalsplus +
20162016
code->co_stacksize);
20172017
PyObject **consts = &PyTuple_GET_ITEM(code->co_consts, 0);
2018-
Py_MEMCPY(const_regs, consts, sizeof(PyObject*) * nconsts);
2018+
memcpy(const_regs, consts, sizeof(PyObject*) * nconsts);
20192019
}
20202020
return frame;
20212021
fail:

Python/compile.c

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ write_instr(_Py_CODEUNIT *codestr, struct instr *instruction, int ilen)
304304
int oparg3 = instruction->i_oparg3.final;
305305

306306
if (0) {
307-
if (opcode == LOAD_FAST_R || opcode == STORE_FAST_R)
307+
if (opcode == LOAD_CONST_R || opcode == LOAD_FAST_R || opcode == STORE_FAST_R)
308308
{
309309
fprintf(stderr,
310310
"write_instr [%d]: oparg = %d oparg1 = %d oparg2 = %d oparg3 = %d\n",
@@ -710,9 +710,10 @@ compiler_setup(struct compiler *c, mod_ty mod, PyObject *filename,
710710
c->c_regcode = false;
711711
}
712712
else {
713-
c->c_regcode = !strstr(f, "import"); // strstr(f, "test_");
713+
c->c_regcode = !strstr(f, "import") && !strstr(f, "frozen") && !strstr(f, "freeze") && !strstr(f, "encodings");
714+
c->c_regcode = strstr(f, "mytest");
714715
}
715-
c->c_regcode = true;
716+
//c->c_regcode = true;
716717

717718
c->c_arena = arena;
718719
if (!_PyFuture_FromAST(mod, filename, &c->c_future)) {
@@ -1223,6 +1224,7 @@ stack_effect(int opcode, int oparg, int jump)
12231224
case DELETE_GLOBAL:
12241225
return 0;
12251226
case LOAD_CONST:
1227+
case LOAD_CONST_R:
12261228
return 1;
12271229
case LOAD_NAME:
12281230
return 1;
@@ -1636,7 +1638,13 @@ compiler_addop_load_const(struct compiler *c, location loc, PyObject *o)
16361638
if (arg < 0) {
16371639
return ERROR;
16381640
}
1639-
return cfg_builder_addop_i(CFG_BUILDER(c), LOAD_CONST, arg, loc);
1641+
if (c->c_regcode) {
1642+
return cfg_builder_addop(CFG_BUILDER(c), LOAD_CONST_R, arg, loc,
1643+
CONST_OPARG(arg), UNUSED_OPARG, UNUSED_OPARG);
1644+
}
1645+
else {
1646+
return cfg_builder_addop_i(CFG_BUILDER(c), LOAD_CONST, arg, loc);
1647+
}
16401648
}
16411649

16421650
static int
@@ -8873,9 +8881,7 @@ resolve_register(oparg_t *oparg, int nlocalsplus, PyObject *varnames,
88738881
break;
88748882
case CONST_REG:
88758883
assert(oparg->value >= 0 && oparg->value < nconsts);
8876-
oparg->final = (nlocalsplus +
8877-
stacksize +
8878-
oparg->value);
8884+
oparg->final = (nlocalsplus + stacksize + oparg->value);
88798885
break;
88808886
case NAME_REG:
88818887
assert(oparg->value >= 0 && oparg->value < nlocalsplus);
@@ -9092,7 +9098,7 @@ get_const_value(int opcode, int oparg, PyObject *co_consts)
90929098
{
90939099
PyObject *constant = NULL;
90949100
assert(HAS_CONST(opcode));
9095-
if (opcode == LOAD_CONST) {
9101+
if (opcode == LOAD_CONST || opcode == LOAD_CONST_R) {
90969102
constant = PyList_GET_ITEM(co_consts, oparg);
90979103
}
90989104

@@ -9385,10 +9391,15 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts)
93859391
switch (inst->i_opcode) {
93869392
/* Remove LOAD_CONST const; conditional jump */
93879393
case LOAD_CONST:
9394+
case LOAD_CONST_R:
93889395
{
93899396
PyObject* cnt;
93909397
int is_true;
93919398
int jump_if_true;
9399+
if (inst->i_opcode == LOAD_CONST_R) {
9400+
oparg = inst->i_oparg1.value;
9401+
}
9402+
93929403
switch(nextop) {
93939404
case POP_JUMP_IF_FALSE:
93949405
case POP_JUMP_IF_TRUE:
@@ -9926,6 +9937,10 @@ remove_unused_consts(basicblock *entryblock, PyObject *consts)
99269937
int index = b->b_instr[i].i_oparg;
99279938
index_map[index] = index;
99289939
}
9940+
if (b->b_instr[i].i_opcode == LOAD_CONST_R) {
9941+
int index = b->b_instr[i].i_oparg1.value;
9942+
index_map[index] = index;
9943+
}
99299944
}
99309945
}
99319946
/* now index_map[i] == i if consts[i] is used, -1 otherwise */
@@ -9985,6 +10000,12 @@ remove_unused_consts(basicblock *entryblock, PyObject *consts)
998510000
assert(reverse_index_map[index] < n_used_consts);
998610001
b->b_instr[i].i_oparg = (int)reverse_index_map[index];
998710002
}
10003+
if (b->b_instr[i].i_opcode == LOAD_CONST_R) {
10004+
int index = b->b_instr[i].i_oparg1.value;
10005+
assert(reverse_index_map[index] >= 0);
10006+
assert(reverse_index_map[index] < n_used_consts);
10007+
b->b_instr[i].i_oparg1.value = (int)reverse_index_map[index];
10008+
}
998810009
}
998910010
}
999010011

Python/generated_cases.c.h

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/opcode_targets.h

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Tools/build/deepfreeze.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -262,10 +262,7 @@ def generate_code(self, name: str, code: types.CodeType) -> str:
262262
self.field(code, "co_argcount")
263263
self.field(code, "co_posonlyargcount")
264264
self.field(code, "co_kwonlyargcount")
265-
num_registers = (len(localsplusnames) +
266-
code.co_stacksize +
267-
len(co_consts))
268-
self.write(f".co_framesize = {num_registers} + FRAME_SPECIALS_SIZE,")
265+
self.write(f".co_framesize = {len(localsplusnames)} + {code.co_stacksize} + {len(code.co_consts)} + FRAME_SPECIALS_SIZE,")
269266
self.field(code, "co_stacksize")
270267
self.field(code, "co_firstlineno")
271268
self.write(f".co_nlocalsplus = {len(localsplusnames)},")

0 commit comments

Comments
 (0)