@@ -1520,17 +1520,29 @@ fblock_unwind_finally_try(struct compiler *c, struct fblockinfo *info, int prese
1520
1520
return 1 ;
1521
1521
}
1522
1522
1523
+ static int
1524
+ compiler_call_exit_with_nones (struct compiler * c ) {
1525
+ PyObject * three_nones = PyTuple_Pack (3 , Py_None , Py_None , Py_None );
1526
+ if (three_nones == NULL ) {
1527
+ return 0 ;
1528
+ }
1529
+ ADDOP_O (c , LOAD_CONST , three_nones , consts );
1530
+ ADDOP_I (c , CALL_FUNCTION_EX , 0 );
1531
+ Py_DECREF (three_nones );
1532
+ return 1 ;
1533
+ }
1534
+
1535
+
1523
1536
static int
1524
1537
fblock_unwind_async_with (struct compiler * c , struct fblockinfo * info , int preserve_tos )
1525
1538
{
1526
1539
ADDOP (c , POP_BLOCK );
1527
1540
if (preserve_tos )
1528
1541
ADDOP (c , ROT_TWO );
1529
1542
/* await __exit__(None, None, None) */
1530
- ADDOP_O (c , LOAD_CONST , Py_None , consts );
1531
- ADDOP (c , DUP_TOP );
1532
- ADDOP (c , DUP_TOP );
1533
- ADDOP_I (c , CALL_FUNCTION , 3 );
1543
+ if (!compiler_call_exit_with_nones (c )) {
1544
+ return 0 ;
1545
+ }
1534
1546
ADDOP (c , GET_AWAITABLE );
1535
1547
ADDOP_O (c , LOAD_CONST , Py_None , consts );
1536
1548
ADDOP (c , YIELD_FROM );
@@ -1569,10 +1581,9 @@ fblock_unwind_with(struct compiler *c, struct fblockinfo *info, int preserve_tos
1569
1581
if (preserve_tos )
1570
1582
ADDOP (c , ROT_TWO );
1571
1583
/* call __exit__(None, None, None) */
1572
- ADDOP_O (c , LOAD_CONST , Py_None , consts );
1573
- ADDOP (c , DUP_TOP );
1574
- ADDOP (c , DUP_TOP );
1575
- ADDOP_I (c , CALL_FUNCTION , 3 );
1584
+ if (!compiler_call_exit_with_nones (c )) {
1585
+ return 0 ;
1586
+ }
1576
1587
ADDOP (c , POP_TOP );
1577
1588
return 1 ;
1578
1589
}
@@ -2658,14 +2669,16 @@ compiler_continue(struct compiler *c)
2658
2669
2659
2670
/* Code generated for "try: <body> finally: <finalbody>" is as follows:
2660
2671
2661
- SETUP_EXCEPT F2
2672
+ SETUP_EXCEPT F1
2662
2673
<code for body>
2663
2674
POP_BLOCK
2664
- F1:
2665
- <code for finalbody>
2666
- JUMP_ABSOLUTE EXIT
2675
+ LOAD_ADDR EXIT
2676
+ JUMP_FORWARD F2
2677
+ F1: LOAD_ADDR R
2667
2678
F2:
2668
2679
<code for finalbody>
2680
+ END_FINALLY
2681
+ R:
2669
2682
RERAISE
2670
2683
EXIT:
2671
2684
@@ -2681,6 +2694,10 @@ compiler_continue(struct compiler *c)
2681
2694
Pops en entry from the block stack, and pops the value
2682
2695
stack until its level is the same as indicated on the
2683
2696
block stack. (The label is ignored.)
2697
+ LOAD_ADDR:
2698
+ Pushes the given address (as an integer) to the value stack.
2699
+ END_FINALLY:
2700
+ Jumps to the address currently on the top of the value stack.
2684
2701
RERAISE:
2685
2702
Pops 3 entries from the *value* stack and re-raises the exception
2686
2703
they specify.
@@ -2725,13 +2742,12 @@ compiler_try_finally(struct compiler *c, stmt_ty s)
2725
2742
compiler_use_next_block (c , final1 );
2726
2743
2727
2744
ADDOP_JREL (c , LOAD_ADDR , exit );
2728
- ADDOP_JABS (c , JUMP_ABSOLUTE , finalbody );
2745
+ ADDOP_JREL (c , JUMP_FORWARD , finalbody );
2729
2746
2730
2747
/* Jump to `finally` block for exceptional outcome */
2731
2748
compiler_use_next_block (c , final2 );
2732
2749
c -> u -> u_lineno_set = 0 ;
2733
2750
ADDOP_JREL (c , LOAD_ADDR , reraise );
2734
- ADDOP_JABS (c , JUMP_ABSOLUTE , finalbody );
2735
2751
2736
2752
/* Actual code for `finally` block */
2737
2753
if (!compiler_push_finally_end (c , finalbody ))
@@ -2858,8 +2874,7 @@ compiler_try_except(struct compiler *c, stmt_ty s)
2858
2874
compiler_nameop (c , handler -> v .ExceptHandler .name , Del );
2859
2875
ADDOP_JREL (c , JUMP_FORWARD , end );
2860
2876
2861
- /* finally: */
2862
- ADDOP_O (c , LOAD_CONST , Py_None , consts );
2877
+ /* cleanup: */
2863
2878
compiler_use_next_block (c , cleanup_end );
2864
2879
if (!compiler_push_finally_end (c , cleanup_end ))
2865
2880
return 0 ;
@@ -4390,18 +4405,6 @@ expr_constant(expr_ty e)
4390
4405
return -1 ;
4391
4406
}
4392
4407
4393
- static int
4394
- compiler_call_exit_with_nones (struct compiler * c ) {
4395
- PyObject * three_nones = PyTuple_Pack (3 , Py_None , Py_None , Py_None );
4396
- if (three_nones == NULL ) {
4397
- return 0 ;
4398
- }
4399
- ADDOP_O (c , LOAD_CONST , three_nones , consts );
4400
- ADDOP_I (c , CALL_FUNCTION_EX , 0 );
4401
- Py_DECREF (three_nones );
4402
- return 1 ;
4403
- }
4404
-
4405
4408
static int
4406
4409
compiler_with_except_finish (struct compiler * c ) {
4407
4410
basicblock * exit ;
@@ -4529,25 +4532,27 @@ compiler_async_with(struct compiler *c, stmt_ty s, int pos)
4529
4532
/*
4530
4533
Implements the with statement from PEP 343.
4531
4534
4532
- The semantics outlined in that PEP are as follows:
4533
-
4534
4535
with EXPR as VAR:
4535
4536
BLOCK
4536
4537
4537
- It is implemented roughly as:
4538
+ is implemented as:
4539
+
4540
+ <code for EXPR>
4541
+ ENTER_WITH
4542
+ SETUP_WITH E
4543
+ <code to store to VAR> or POP_TOP
4544
+ <code for BLOCK>
4545
+ LOAD_CONST (None, None, None)
4546
+ CALL_FUNCTION_EX 0
4547
+ JUMP_FORWARD EXIT
4548
+ E: WITH_EXCEPT_START (calls EXPR.__exit__)
4549
+ POP_JUMP_IF_TRUE T:
4550
+ RERAISE
4551
+ T: POP_TOP * 3 (remove exception from stack)
4552
+ POP_EXCEPT
4553
+ POP_TOP
4554
+ EXIT:
4538
4555
4539
- context = EXPR
4540
- exit = context.__exit__ # not calling it
4541
- value = context.__enter__()
4542
- try:
4543
- VAR = value # if VAR present in the syntax
4544
- BLOCK
4545
- finally:
4546
- if an exception was raised:
4547
- exc = copy of (exception, instance, traceback)
4548
- else:
4549
- exc = (None, None, None)
4550
- exit(*exc)
4551
4556
*/
4552
4557
4553
4558
static int
@@ -4604,7 +4609,7 @@ compiler_with(struct compiler *c, stmt_ty s, int pos)
4604
4609
return 0 ;
4605
4610
ADDOP (c , POP_TOP );
4606
4611
compiler_pop_fblock (c , FINALLY_END , final1 );
4607
- ADDOP_JABS (c , JUMP_ABSOLUTE , exit );
4612
+ ADDOP_JREL (c , JUMP_FORWARD , exit );
4608
4613
4609
4614
/* `finally` block for exceptional outcome */
4610
4615
compiler_use_next_block (c , final2 );
0 commit comments