@@ -160,6 +160,8 @@ struct compiler {
160
160
int c_interactive ; /* true if in interactive mode */
161
161
int c_nestlevel ;
162
162
163
+ PyObject * c_const_cache ; /* Python dict holding all constants,
164
+ including names tuple */
163
165
struct compiler_unit * u ; /* compiler state for current block */
164
166
PyObject * c_stack ; /* Python list holding compiler_unit ptrs */
165
167
PyArena * c_arena ; /* pointer to memory allocation arena */
@@ -285,9 +287,16 @@ compiler_init(struct compiler *c)
285
287
{
286
288
memset (c , 0 , sizeof (struct compiler ));
287
289
290
+ c -> c_const_cache = PyDict_New ();
291
+ if (!c -> c_const_cache ) {
292
+ return 0 ;
293
+ }
294
+
288
295
c -> c_stack = PyList_New (0 );
289
- if (!c -> c_stack )
296
+ if (!c -> c_stack ) {
297
+ Py_CLEAR (c -> c_const_cache );
290
298
return 0 ;
299
+ }
291
300
292
301
return 1 ;
293
302
}
@@ -387,6 +396,7 @@ compiler_free(struct compiler *c)
387
396
if (c -> c_future )
388
397
PyObject_Free (c -> c_future );
389
398
Py_XDECREF (c -> c_filename );
399
+ Py_DECREF (c -> c_const_cache );
390
400
Py_DECREF (c -> c_stack );
391
401
}
392
402
@@ -1179,18 +1189,121 @@ compiler_add_o(struct compiler *c, PyObject *dict, PyObject *o)
1179
1189
return arg ;
1180
1190
}
1181
1191
1192
+ // Merge const *o* recursively and return constant key object.
1193
+ static PyObject *
1194
+ merge_consts_recursive (struct compiler * c , PyObject * o )
1195
+ {
1196
+ // None and Ellipsis are singleton, and key is the singleton.
1197
+ // No need to merge object and key.
1198
+ if (o == Py_None || o == Py_Ellipsis ) {
1199
+ Py_INCREF (o );
1200
+ return o ;
1201
+ }
1202
+
1203
+ PyObject * key = _PyCode_ConstantKey (o );
1204
+ if (key == NULL ) {
1205
+ return NULL ;
1206
+ }
1207
+
1208
+ // t is borrowed reference
1209
+ PyObject * t = PyDict_SetDefault (c -> c_const_cache , key , key );
1210
+ if (t != key ) {
1211
+ Py_INCREF (t );
1212
+ Py_DECREF (key );
1213
+ return t ;
1214
+ }
1215
+
1216
+ if (PyTuple_CheckExact (o )) {
1217
+ Py_ssize_t i , len = PyTuple_GET_SIZE (o );
1218
+ for (i = 0 ; i < len ; i ++ ) {
1219
+ PyObject * item = PyTuple_GET_ITEM (o , i );
1220
+ PyObject * u = merge_consts_recursive (c , item );
1221
+ if (u == NULL ) {
1222
+ Py_DECREF (key );
1223
+ return NULL ;
1224
+ }
1225
+
1226
+ // See _PyCode_ConstantKey()
1227
+ PyObject * v ; // borrowed
1228
+ if (PyTuple_CheckExact (u )) {
1229
+ v = PyTuple_GET_ITEM (u , 1 );
1230
+ }
1231
+ else {
1232
+ v = u ;
1233
+ }
1234
+ if (v != item ) {
1235
+ Py_INCREF (v );
1236
+ PyTuple_SET_ITEM (o , i , v );
1237
+ Py_DECREF (item );
1238
+ }
1239
+
1240
+ Py_DECREF (u );
1241
+ }
1242
+ }
1243
+ else if (PyFrozenSet_CheckExact (o )) {
1244
+ // We register items in the frozenset, but don't rewrite
1245
+ // the frozenset when the item is already registered
1246
+ // because frozenset is rare and difficult.
1247
+
1248
+ // *key* is tuple. And it's first item is frozenset of
1249
+ // constant keys.
1250
+ // See _PyCode_ConstantKey() for detail.
1251
+ assert (PyTuple_CheckExact (key ));
1252
+ assert (PyTuple_GET_SIZE (key ) == 2 );
1253
+
1254
+ Py_ssize_t len = PySet_GET_SIZE (o );
1255
+ if (len == 0 ) {
1256
+ return key ;
1257
+ }
1258
+ PyObject * tuple = PyTuple_New (len );
1259
+ if (tuple == NULL ) {
1260
+ Py_DECREF (key );
1261
+ return NULL ;
1262
+ }
1263
+ Py_ssize_t i = 0 , pos = 0 ;
1264
+ PyObject * item ;
1265
+ Py_hash_t hash ;
1266
+ while (_PySet_NextEntry (o , & pos , & item , & hash )) {
1267
+ PyObject * k = merge_consts_recursive (c , item );
1268
+ if (k == NULL ) {
1269
+ Py_DECREF (tuple );
1270
+ Py_DECREF (key );
1271
+ return NULL ;
1272
+ }
1273
+ PyObject * u ;
1274
+ if (PyTuple_CheckExact (k )) {
1275
+ u = PyTuple_GET_ITEM (k , 1 );
1276
+ }
1277
+ else {
1278
+ u = k ;
1279
+ }
1280
+ Py_INCREF (u );
1281
+ PyTuple_SET_ITEM (tuple , i , u );
1282
+ i ++ ;
1283
+ }
1284
+
1285
+ PyObject * new = PyFrozenSet_New (tuple );
1286
+ Py_DECREF (tuple );
1287
+ if (new == NULL ) {
1288
+ Py_DECREF (key );
1289
+ return NULL ;
1290
+ }
1291
+ PyTuple_SET_ITEM (key , 1 , new );
1292
+ }
1293
+
1294
+ return key ;
1295
+ }
1296
+
1182
1297
static Py_ssize_t
1183
1298
compiler_add_const (struct compiler * c , PyObject * o )
1184
1299
{
1185
- PyObject * t ;
1186
- Py_ssize_t arg ;
1187
-
1188
- t = _PyCode_ConstantKey (o );
1189
- if (t == NULL )
1300
+ PyObject * key = merge_consts_recursive (c , o );
1301
+ if (key == NULL ) {
1190
1302
return -1 ;
1303
+ }
1191
1304
1192
- arg = compiler_add_o (c , c -> u -> u_consts , t );
1193
- Py_DECREF (t );
1305
+ Py_ssize_t arg = compiler_add_o (c , c -> u -> u_consts , key );
1306
+ Py_DECREF (key );
1194
1307
return arg ;
1195
1308
}
1196
1309
@@ -5380,6 +5493,35 @@ compute_code_flags(struct compiler *c)
5380
5493
return flags ;
5381
5494
}
5382
5495
5496
+ // Merge *tuple* with constant cache.
5497
+ // Unlike merge_consts_recursive(), this function doesn't work recursively.
5498
+ static int
5499
+ merge_const_tuple (struct compiler * c , PyObject * * tuple )
5500
+ {
5501
+ assert (PyTuple_CheckExact (* tuple ));
5502
+
5503
+ PyObject * key = _PyCode_ConstantKey (* tuple );
5504
+ if (key == NULL ) {
5505
+ return 0 ;
5506
+ }
5507
+
5508
+ // t is borrowed reference
5509
+ PyObject * t = PyDict_SetDefault (c -> c_const_cache , key , key );
5510
+ Py_DECREF (key );
5511
+ if (t == NULL ) {
5512
+ return 0 ;
5513
+ }
5514
+ if (t == key ) { // tuple is new constant.
5515
+ return 1 ;
5516
+ }
5517
+
5518
+ PyObject * u = PyTuple_GET_ITEM (t , 1 );
5519
+ Py_INCREF (u );
5520
+ Py_DECREF (* tuple );
5521
+ * tuple = u ;
5522
+ return 1 ;
5523
+ }
5524
+
5383
5525
static PyCodeObject *
5384
5526
makecode (struct compiler * c , struct assembler * a )
5385
5527
{
@@ -5410,6 +5552,14 @@ makecode(struct compiler *c, struct assembler *a)
5410
5552
if (!freevars )
5411
5553
goto error ;
5412
5554
5555
+ if (!merge_const_tuple (c , & names ) ||
5556
+ !merge_const_tuple (c , & varnames ) ||
5557
+ !merge_const_tuple (c , & cellvars ) ||
5558
+ !merge_const_tuple (c , & freevars ))
5559
+ {
5560
+ goto error ;
5561
+ }
5562
+
5413
5563
nlocals = PyDict_GET_SIZE (c -> u -> u_varnames );
5414
5564
assert (nlocals < INT_MAX );
5415
5565
nlocals_int = Py_SAFE_DOWNCAST (nlocals , Py_ssize_t , int );
@@ -5427,6 +5577,9 @@ makecode(struct compiler *c, struct assembler *a)
5427
5577
goto error ;
5428
5578
Py_DECREF (consts );
5429
5579
consts = tmp ;
5580
+ if (!merge_const_tuple (c , & consts )) {
5581
+ goto error ;
5582
+ }
5430
5583
5431
5584
argcount = Py_SAFE_DOWNCAST (c -> u -> u_argcount , Py_ssize_t , int );
5432
5585
kwonlyargcount = Py_SAFE_DOWNCAST (c -> u -> u_kwonlyargcount , Py_ssize_t , int );
0 commit comments