bpo-29469: peephole: Remove const_stack (GH-4879) · python/cpython@87010e8 (original) (raw)

`@@ -23,51 +23,6 @@

`

23

23

` (blocks[start]==blocks[end])

`

24

24

``

25

25

``

26

``

`-

#define CONST_STACK_CREATE() { \

`

27

``

`-

const_stack_size = 256; \

`

28

``

`-

const_stack = PyMem_New(PyObject *, const_stack_size); \

`

29

``

`-

if (!const_stack) { \

`

30

``

`-

PyErr_NoMemory(); \

`

31

``

`-

goto exitError; \

`

32

``

`-

} \

`

33

``

`-

}

`

34

``

-

35

``

`-

#define CONST_STACK_DELETE() do { \

`

36

``

`-

if (const_stack) \

`

37

``

`-

PyMem_Free(const_stack); \

`

38

``

`-

} while(0)

`

39

``

-

40

``

`-

#define CONST_STACK_LEN() ((unsigned)(const_stack_top + 1))

`

41

``

-

42

``

`-

#define CONST_STACK_PUSH_OP(i) do { \

`

43

``

`-

PyObject *_x; \

`

44

``

`-

assert(_Py_OPCODE(codestr[i]) == LOAD_CONST); \

`

45

``

`-

assert(PyList_GET_SIZE(consts) > (Py_ssize_t)get_arg(codestr, i)); \

`

46

``

`-

_x = PyList_GET_ITEM(consts, get_arg(codestr, i)); \

`

47

``

`-

if (++const_stack_top >= const_stack_size) { \

`

48

``

`-

const_stack_size *= 2; \

`

49

``

`-

PyMem_Resize(const_stack, PyObject *, const_stack_size); \

`

50

``

`-

if (!const_stack) { \

`

51

``

`-

PyErr_NoMemory(); \

`

52

``

`-

goto exitError; \

`

53

``

`-

} \

`

54

``

`-

} \

`

55

``

`-

const_stack[const_stack_top] = _x; \

`

56

``

`-

in_consts = 1; \

`

57

``

`-

} while(0)

`

58

``

-

59

``

`-

#define CONST_STACK_RESET() do { \

`

60

``

`-

const_stack_top = -1; \

`

61

``

`-

} while(0)

`

62

``

-

63

``

`-

#define CONST_STACK_LASTN(i) \

`

64

``

`-

&const_stack[CONST_STACK_LEN() - i]

`

65

``

-

66

``

`-

#define CONST_STACK_POP(i) do { \

`

67

``

`-

assert(CONST_STACK_LEN() >= i); \

`

68

``

`-

const_stack_top -= i; \

`

69

``

`-

} while(0)

`

70

``

-

71

26

`/* Scans back N consecutive LOAD_CONST instructions, skipping NOPs,

`

72

27

` returns index of the Nth last's LOAD_CONST's EXTENDED_ARG prefix.

`

73

28

` Callers are responsible to check CONST_STACK_LEN beforehand.

`

`@@ -88,8 +43,7 @@ lastn_const_start(const _Py_CODEUNIT *codestr, Py_ssize_t i, Py_ssize_t n)

`

88

43

` }

`

89

44

` }

`

90

45

`else {

`

91

``

`-

assert(_Py_OPCODE(codestr[i]) == NOP ||

`

92

``

`-

_Py_OPCODE(codestr[i]) == EXTENDED_ARG);

`

``

46

`+

assert(_Py_OPCODE(codestr[i]) == EXTENDED_ARG);

`

93

47

` }

`

94

48

` }

`

95

49

`}

`

`@@ -172,39 +126,40 @@ copy_op_arg(_Py_CODEUNIT *codestr, Py_ssize_t i, unsigned char op,

`

172

126

` The consts table must still be in list form so that the

`

173

127

` new constant (c1, c2, ... cn) can be appended.

`

174

128

` Called with codestr pointing to the first LOAD_CONST.

`

175

``

`-

Bails out with no change if one or more of the LOAD_CONSTs is missing.

`

176

129

`*/

`

177

130

`static Py_ssize_t

`

178

131

`fold_tuple_on_constants(_Py_CODEUNIT *codestr, Py_ssize_t c_start,

`

179

``

`-

Py_ssize_t opcode_end, unsigned char opcode,

`

180

``

`-

PyObject *consts, PyObject **objs, int n)

`

``

132

`+

Py_ssize_t opcode_end, PyObject *consts, int n)

`

181

133

`{

`

182

``

`-

PyObject *newconst, *constant;

`

183

``

`-

Py_ssize_t i, len_consts;

`

184

``

-

185

134

`/* Pre-conditions */

`

186

135

`assert(PyList_CheckExact(consts));

`

187

136

``

188

137

`/* Buildup new tuple of constants */

`

189

``

`-

newconst = PyTuple_New(n);

`

``

138

`+

PyObject *newconst = PyTuple_New(n);

`

190

139

`if (newconst == NULL) {

`

191

140

`return -1;

`

192

141

` }

`

193

``

`-

for (i=0 ; i<n ; i++) {

`

194

``

`-

constant = objs[i];

`

``

142

+

``

143

`+

for (Py_ssize_t i = 0, pos = c_start; i < n; i++, pos++) {

`

``

144

`+

assert(pos < opcode_end);

`

``

145

`+

pos = find_op(codestr, pos);

`

``

146

`+

assert(_Py_OPCODE(codestr[pos]) == LOAD_CONST);

`

``

147

+

``

148

`+

unsigned int arg = get_arg(codestr, pos);

`

``

149

`+

PyObject *constant = PyList_GET_ITEM(consts, arg);

`

195

150

`Py_INCREF(constant);

`

196

151

`PyTuple_SET_ITEM(newconst, i, constant);

`

197

152

` }

`

198

153

``

199

154

`/* Append folded constant onto consts */

`

200

``

`-

len_consts = PyList_GET_SIZE(consts);

`

201

155

`if (PyList_Append(consts, newconst)) {

`

202

156

`Py_DECREF(newconst);

`

203

157

`return -1;

`

204

158

` }

`

205

159

`Py_DECREF(newconst);

`

206

160

``

207

``

`-

return copy_op_arg(codestr, c_start, LOAD_CONST, len_consts, opcode_end);

`

``

161

`+

return copy_op_arg(codestr, c_start, LOAD_CONST,

`

``

162

`+

PyList_GET_SIZE(consts)-1, opcode_end);

`

208

163

`}

`

209

164

``

210

165

`static unsigned int *

`

`@@ -274,10 +229,8 @@ PyCode_Optimize(PyObject code, PyObject consts, PyObject *names,

`

274

229

`unsigned char *lnotab;

`

275

230

`unsigned int cum_orig_offset, last_offset;

`

276

231

`Py_ssize_t tabsiz;

`

277

``

`-

PyObject **const_stack = NULL;

`

278

``

`-

Py_ssize_t const_stack_top = -1;

`

279

``

`-

Py_ssize_t const_stack_size = 0;

`

280

``

`-

int in_consts = 0; /* whether we are in a LOAD_CONST sequence */

`

``

232

`+

// Count runs of consecutive LOAD_CONSTs

`

``

233

`+

unsigned int cumlc = 0, lastlc = 0;

`

281

234

`unsigned int *blocks = NULL;

`

282

235

``

283

236

`/* Bail out if an exception is set */

`

`@@ -314,8 +267,6 @@ PyCode_Optimize(PyObject code, PyObject consts, PyObject *names,

`

314

267

` goto exitError;

`

315

268

`assert(PyList_Check(consts));

`

316

269

``

317

``

`-

CONST_STACK_CREATE();

`

318

``

-

319

270

`for (i=find_op(codestr, 0) ; i<codelen ; i=nexti) {

`

320

271

`opcode = _Py_OPCODE(codestr[i]);

`

321

272

`op_start = i;

`

`@@ -328,23 +279,21 @@ PyCode_Optimize(PyObject code, PyObject consts, PyObject *names,

`

328

279

`nexti++;

`

329

280

`nextop = nexti < codelen ? _Py_OPCODE(codestr[nexti]) : 0;

`

330

281

``

331

``

`-

if (!in_consts) {

`

332

``

`-

CONST_STACK_RESET();

`

333

``

`-

}

`

334

``

`-

in_consts = 0;

`

``

282

`+

lastlc = cumlc;

`

``

283

`+

cumlc = 0;

`

335

284

``

336

285

`switch (opcode) {

`

337

286

`/* Skip over LOAD_CONST trueconst

`

338

287

` POP_JUMP_IF_FALSE xx. This improves

`

339

288

` "while 1" performance. */

`

340

289

`case LOAD_CONST:

`

341

``

`-

CONST_STACK_PUSH_OP(i);

`

``

290

`+

cumlc = lastlc + 1;

`

342

291

`if (nextop != POP_JUMP_IF_FALSE ||

`

343

292

` !ISBASICBLOCK(blocks, op_start, i + 1) ||

`

344

293

` !PyObject_IsTrue(PyList_GET_ITEM(consts, get_arg(codestr, i))))

`

345

294

`break;

`

346

295

`fill_nops(codestr, op_start, nexti + 1);

`

347

``

`-

CONST_STACK_POP(1);

`

``

296

`+

cumlc = 0;

`

348

297

`break;

`

349

298

``

350

299

`/* Try to fold tuples of constants.

`

`@@ -353,15 +302,10 @@ PyCode_Optimize(PyObject code, PyObject consts, PyObject *names,

`

353

302

` Replace BUILD_SEQN 3 UNPACK_SEQN 3 with ROT3 ROT2. */

`

354

303

`case BUILD_TUPLE:

`

355

304

`j = get_arg(codestr, i);

`

356

``

`-

if (j > 0 && CONST_STACK_LEN() >= j) {

`

``

305

`+

if (j > 0 && lastlc >= j) {

`

357

306

`h = lastn_const_start(codestr, op_start, j);

`

358

307

`if (ISBASICBLOCK(blocks, h, op_start)) {

`

359

``

`-

h = fold_tuple_on_constants(codestr, h, i + 1, opcode,

`

360

``

`-

consts, CONST_STACK_LASTN(j), j);

`

361

``

`-

if (h >= 0) {

`

362

``

`-

CONST_STACK_POP(j);

`

363

``

`-

CONST_STACK_PUSH_OP(h);

`

364

``

`-

}

`

``

308

`+

h = fold_tuple_on_constants(codestr, h, i+1, consts, j);

`

365

309

`break;

`

366

310

` }

`

367

311

` }

`

`@@ -374,12 +318,10 @@ PyCode_Optimize(PyObject code, PyObject consts, PyObject *names,

`

374

318

` } else if (j == 2) {

`

375

319

`codestr[op_start] = PACKOPARG(ROT_TWO, 0);

`

376

320

`fill_nops(codestr, op_start + 1, nexti + 1);

`

377

``

`-

CONST_STACK_RESET();

`

378

321

` } else if (j == 3) {

`

379

322

`codestr[op_start] = PACKOPARG(ROT_THREE, 0);

`

380

323

`codestr[op_start + 1] = PACKOPARG(ROT_TWO, 0);

`

381

324

`fill_nops(codestr, op_start + 2, nexti + 1);

`

382

``

`-

CONST_STACK_RESET();

`

383

325

` }

`

384

326

`break;

`

385

327

``

`@@ -538,7 +480,6 @@ PyCode_Optimize(PyObject code, PyObject consts, PyObject *names,

`

538

480

` }

`

539

481

`assert(h + (Py_ssize_t)nops == codelen);

`

540

482

``

541

``

`-

CONST_STACK_DELETE();

`

542

483

`PyMem_Free(blocks);

`

543

484

`code = PyBytes_FromStringAndSize((char *)codestr, h * sizeof(_Py_CODEUNIT));

`

544

485

`PyMem_Free(codestr);

`

`@@ -549,7 +490,6 @@ PyCode_Optimize(PyObject code, PyObject consts, PyObject *names,

`

549

490

``

550

491

`exitUnchanged:

`

551

492

`Py_XINCREF(code);

`

552

``

`-

CONST_STACK_DELETE();

`

553

493

`PyMem_Free(blocks);

`

554

494

`PyMem_Free(codestr);

`

555

495

`return code;

`