Skip to content

Commit 7495750

Browse files
committed
vm: Record exception ip only for instructions where exceptions may happen.
Mirroring ip to a volatile memory variable for each opcode is an expensive operation. For quite a lot of often executed opcodes like stack manipulation or jumps, exceptions cannot actually happen. So, record ip only for opcode where that's possible.
1 parent 1570eaf commit 7495750

1 file changed

Lines changed: 58 additions & 2 deletions

File tree

py/vm.c

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,19 @@ typedef enum {
101101
// MP_VM_RETURN_YIELD, ip, sp valid, yielded value in *sp
102102
// MP_VM_RETURN_EXCEPTION, exception in fastn[0]
103103
mp_vm_return_kind_t mp_execute_bytecode(mp_code_state *code_state, volatile mp_obj_t inject_exc) {
104+
#define SELECTIVE_EXC_IP (0)
105+
#if SELECTIVE_EXC_IP
106+
#define MARK_EXC_IP_SELECTIVE() { code_state->ip = ip - 1; }
107+
#define MARK_EXC_IP_GLOBAL()
108+
#else
109+
#define MARK_EXC_IP_SELECTIVE()
110+
#define MARK_EXC_IP_GLOBAL() { code_state->ip = ip; }
111+
#endif
104112
#if MICROPY_OPT_COMPUTED_GOTO
105113
#include "vmentrytable.h"
106114
#define DISPATCH() do { \
107115
TRACE(ip); \
108-
code_state->ip = ip; \
116+
MARK_EXC_IP_GLOBAL(); \
109117
goto *entry_table[*ip++]; \
110118
} while(0)
111119
#define DISPATCH_WITH_PEND_EXC_CHECK() goto pending_exception_check
@@ -161,7 +169,7 @@ mp_vm_return_kind_t mp_execute_bytecode(mp_code_state *code_state, volatile mp_o
161169
DISPATCH();
162170
#else
163171
TRACE(ip);
164-
code_state->ip = ip;
172+
MARK_EXC_IP_GLOBAL();
165173
switch (*ip++) {
166174
#endif
167175

@@ -201,6 +209,7 @@ mp_vm_return_kind_t mp_execute_bytecode(mp_code_state *code_state, volatile mp_o
201209
}
202210

203211
ENTRY(MP_BC_LOAD_CONST_DEC): {
212+
MARK_EXC_IP_SELECTIVE();
204213
DECODE_QSTR;
205214
PUSH(mp_load_const_dec(qst));
206215
DISPATCH();
@@ -228,6 +237,7 @@ mp_vm_return_kind_t mp_execute_bytecode(mp_code_state *code_state, volatile mp_o
228237
load_check:
229238
if (obj_shared == MP_OBJ_NULL) {
230239
local_name_error: {
240+
MARK_EXC_IP_SELECTIVE();
231241
mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NameError, "local variable referenced before assignment");
232242
RAISE(obj);
233243
}
@@ -243,35 +253,41 @@ mp_vm_return_kind_t mp_execute_bytecode(mp_code_state *code_state, volatile mp_o
243253
}
244254

245255
ENTRY(MP_BC_LOAD_NAME): {
256+
MARK_EXC_IP_SELECTIVE();
246257
DECODE_QSTR;
247258
PUSH(mp_load_name(qst));
248259
DISPATCH();
249260
}
250261

251262
ENTRY(MP_BC_LOAD_GLOBAL): {
263+
MARK_EXC_IP_SELECTIVE();
252264
DECODE_QSTR;
253265
PUSH(mp_load_global(qst));
254266
DISPATCH();
255267
}
256268

257269
ENTRY(MP_BC_LOAD_ATTR): {
270+
MARK_EXC_IP_SELECTIVE();
258271
DECODE_QSTR;
259272
SET_TOP(mp_load_attr(TOP(), qst));
260273
DISPATCH();
261274
}
262275

263276
ENTRY(MP_BC_LOAD_METHOD): {
277+
MARK_EXC_IP_SELECTIVE();
264278
DECODE_QSTR;
265279
mp_load_method(*sp, qst, sp);
266280
sp += 1;
267281
DISPATCH();
268282
}
269283

270284
ENTRY(MP_BC_LOAD_BUILD_CLASS):
285+
MARK_EXC_IP_SELECTIVE();
271286
PUSH(mp_load_build_class());
272287
DISPATCH();
273288

274289
ENTRY(MP_BC_LOAD_SUBSCR): {
290+
MARK_EXC_IP_SELECTIVE();
275291
mp_obj_t index = POP();
276292
SET_TOP(mp_obj_subscr(TOP(), index, MP_OBJ_SENTINEL));
277293
DISPATCH();
@@ -290,30 +306,35 @@ mp_vm_return_kind_t mp_execute_bytecode(mp_code_state *code_state, volatile mp_o
290306
}
291307

292308
ENTRY(MP_BC_STORE_NAME): {
309+
MARK_EXC_IP_SELECTIVE();
293310
DECODE_QSTR;
294311
mp_store_name(qst, POP());
295312
DISPATCH();
296313
}
297314

298315
ENTRY(MP_BC_STORE_GLOBAL): {
316+
MARK_EXC_IP_SELECTIVE();
299317
DECODE_QSTR;
300318
mp_store_global(qst, POP());
301319
DISPATCH();
302320
}
303321

304322
ENTRY(MP_BC_STORE_ATTR): {
323+
MARK_EXC_IP_SELECTIVE();
305324
DECODE_QSTR;
306325
mp_store_attr(sp[0], qst, sp[-1]);
307326
sp -= 2;
308327
DISPATCH();
309328
}
310329

311330
ENTRY(MP_BC_STORE_SUBSCR):
331+
MARK_EXC_IP_SELECTIVE();
312332
mp_obj_subscr(sp[-1], sp[0], sp[-2]);
313333
sp -= 3;
314334
DISPATCH();
315335

316336
ENTRY(MP_BC_DELETE_FAST): {
337+
MARK_EXC_IP_SELECTIVE();
317338
DECODE_UINT;
318339
if (fastn[-unum] == MP_OBJ_NULL) {
319340
goto local_name_error;
@@ -323,6 +344,7 @@ mp_vm_return_kind_t mp_execute_bytecode(mp_code_state *code_state, volatile mp_o
323344
}
324345

325346
ENTRY(MP_BC_DELETE_DEREF): {
347+
MARK_EXC_IP_SELECTIVE();
326348
DECODE_UINT;
327349
if (mp_obj_cell_get(fastn[-unum]) == MP_OBJ_NULL) {
328350
goto local_name_error;
@@ -332,12 +354,14 @@ mp_vm_return_kind_t mp_execute_bytecode(mp_code_state *code_state, volatile mp_o
332354
}
333355

334356
ENTRY(MP_BC_DELETE_NAME): {
357+
MARK_EXC_IP_SELECTIVE();
335358
DECODE_QSTR;
336359
mp_delete_name(qst);
337360
DISPATCH();
338361
}
339362

340363
ENTRY(MP_BC_DELETE_GLOBAL): {
364+
MARK_EXC_IP_SELECTIVE();
341365
DECODE_QSTR;
342366
mp_delete_global(qst);
343367
DISPATCH();
@@ -417,6 +441,7 @@ mp_vm_return_kind_t mp_execute_bytecode(mp_code_state *code_state, volatile mp_o
417441
}
418442

419443
ENTRY(MP_BC_SETUP_WITH): {
444+
MARK_EXC_IP_SELECTIVE();
420445
mp_obj_t obj = TOP();
421446
SET_TOP(mp_load_attr(obj, MP_QSTR___exit__));
422447
mp_load_method(obj, MP_QSTR___enter__, sp + 1);
@@ -427,6 +452,7 @@ mp_vm_return_kind_t mp_execute_bytecode(mp_code_state *code_state, volatile mp_o
427452
}
428453

429454
ENTRY(MP_BC_WITH_CLEANUP): {
455+
MARK_EXC_IP_SELECTIVE();
430456
// Arriving here, there's "exception control block" on top of stack,
431457
// and __exit__ bound method underneath it. Bytecode calls __exit__,
432458
// and "deletes" it off stack, shifting "exception control block"
@@ -486,6 +512,7 @@ mp_vm_return_kind_t mp_execute_bytecode(mp_code_state *code_state, volatile mp_o
486512
}
487513

488514
ENTRY(MP_BC_UNWIND_JUMP): {
515+
MARK_EXC_IP_SELECTIVE();
489516
DECODE_SLABEL;
490517
PUSH((void*)(ip + slab)); // push destination ip for jump
491518
PUSH((void*)(mp_uint_t)(*ip)); // push number of exception handlers to unwind (0x80 bit set if we also need to pop stack)
@@ -517,11 +544,13 @@ unwind_jump:;
517544
// matched against: POP_BLOCK or POP_EXCEPT (anything else?)
518545
ENTRY(MP_BC_SETUP_EXCEPT):
519546
ENTRY(MP_BC_SETUP_FINALLY): {
547+
MARK_EXC_IP_SELECTIVE();
520548
PUSH_EXC_BLOCK((*code_state->ip == MP_BC_SETUP_FINALLY) ? 1 : 0);
521549
DISPATCH();
522550
}
523551

524552
ENTRY(MP_BC_END_FINALLY):
553+
MARK_EXC_IP_SELECTIVE();
525554
// not fully implemented
526555
// if TOS is an exception, reraises the exception (3 values on TOS)
527556
// if TOS is None, just pops it and continues
@@ -549,10 +578,12 @@ unwind_jump:;
549578
DISPATCH();
550579

551580
ENTRY(MP_BC_GET_ITER):
581+
MARK_EXC_IP_SELECTIVE();
552582
SET_TOP(mp_getiter(TOP()));
553583
DISPATCH();
554584

555585
ENTRY(MP_BC_FOR_ITER): {
586+
MARK_EXC_IP_SELECTIVE();
556587
DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
557588
code_state->sp = sp;
558589
assert(TOP());
@@ -594,20 +625,23 @@ unwind_jump:;
594625
DISPATCH();
595626

596627
ENTRY(MP_BC_BUILD_TUPLE): {
628+
MARK_EXC_IP_SELECTIVE();
597629
DECODE_UINT;
598630
sp -= unum - 1;
599631
SET_TOP(mp_obj_new_tuple(unum, sp));
600632
DISPATCH();
601633
}
602634

603635
ENTRY(MP_BC_BUILD_LIST): {
636+
MARK_EXC_IP_SELECTIVE();
604637
DECODE_UINT;
605638
sp -= unum - 1;
606639
SET_TOP(mp_obj_new_list(unum, sp));
607640
DISPATCH();
608641
}
609642

610643
ENTRY(MP_BC_LIST_APPEND): {
644+
MARK_EXC_IP_SELECTIVE();
611645
DECODE_UINT;
612646
// I think it's guaranteed by the compiler that sp[unum] is a list
613647
mp_obj_list_append(sp[-unum], sp[0]);
@@ -616,17 +650,20 @@ unwind_jump:;
616650
}
617651

618652
ENTRY(MP_BC_BUILD_MAP): {
653+
MARK_EXC_IP_SELECTIVE();
619654
DECODE_UINT;
620655
PUSH(mp_obj_new_dict(unum));
621656
DISPATCH();
622657
}
623658

624659
ENTRY(MP_BC_STORE_MAP):
660+
MARK_EXC_IP_SELECTIVE();
625661
sp -= 2;
626662
mp_obj_dict_store(sp[0], sp[2], sp[1]);
627663
DISPATCH();
628664

629665
ENTRY(MP_BC_MAP_ADD): {
666+
MARK_EXC_IP_SELECTIVE();
630667
DECODE_UINT;
631668
// I think it's guaranteed by the compiler that sp[-unum - 1] is a map
632669
mp_obj_dict_store(sp[-unum - 1], sp[0], sp[-1]);
@@ -636,13 +673,15 @@ unwind_jump:;
636673

637674
#if MICROPY_PY_BUILTINS_SET
638675
ENTRY(MP_BC_BUILD_SET): {
676+
MARK_EXC_IP_SELECTIVE();
639677
DECODE_UINT;
640678
sp -= unum - 1;
641679
SET_TOP(mp_obj_new_set(unum, sp));
642680
DISPATCH();
643681
}
644682

645683
ENTRY(MP_BC_SET_ADD): {
684+
MARK_EXC_IP_SELECTIVE();
646685
DECODE_UINT;
647686
// I think it's guaranteed by the compiler that sp[-unum] is a set
648687
mp_obj_set_store(sp[-unum], sp[0]);
@@ -653,6 +692,7 @@ unwind_jump:;
653692

654693
#if MICROPY_PY_BUILTINS_SLICE
655694
ENTRY(MP_BC_BUILD_SLICE): {
695+
MARK_EXC_IP_SELECTIVE();
656696
DECODE_UINT;
657697
if (unum == 2) {
658698
mp_obj_t stop = POP();
@@ -669,13 +709,15 @@ unwind_jump:;
669709
#endif
670710

671711
ENTRY(MP_BC_UNPACK_SEQUENCE): {
712+
MARK_EXC_IP_SELECTIVE();
672713
DECODE_UINT;
673714
mp_unpack_sequence(sp[0], unum, sp);
674715
sp += unum - 1;
675716
DISPATCH();
676717
}
677718

678719
ENTRY(MP_BC_UNPACK_EX): {
720+
MARK_EXC_IP_SELECTIVE();
679721
DECODE_UINT;
680722
mp_unpack_ex(sp[0], unum, sp);
681723
sp += (unum & 0xff) + ((unum >> 8) & 0xff);
@@ -715,6 +757,7 @@ unwind_jump:;
715757
}
716758

717759
ENTRY(MP_BC_CALL_FUNCTION): {
760+
MARK_EXC_IP_SELECTIVE();
718761
DECODE_UINT;
719762
// unum & 0xff == n_positional
720763
// (unum >> 8) & 0xff == n_keyword
@@ -724,6 +767,7 @@ unwind_jump:;
724767
}
725768

726769
ENTRY(MP_BC_CALL_FUNCTION_VAR_KW): {
770+
MARK_EXC_IP_SELECTIVE();
727771
DECODE_UINT;
728772
// unum & 0xff == n_positional
729773
// (unum >> 8) & 0xff == n_keyword
@@ -735,6 +779,7 @@ unwind_jump:;
735779
}
736780

737781
ENTRY(MP_BC_CALL_METHOD): {
782+
MARK_EXC_IP_SELECTIVE();
738783
DECODE_UINT;
739784
// unum & 0xff == n_positional
740785
// (unum >> 8) & 0xff == n_keyword
@@ -744,6 +789,7 @@ unwind_jump:;
744789
}
745790

746791
ENTRY(MP_BC_CALL_METHOD_VAR_KW): {
792+
MARK_EXC_IP_SELECTIVE();
747793
DECODE_UINT;
748794
// unum & 0xff == n_positional
749795
// (unum >> 8) & 0xff == n_keyword
@@ -755,6 +801,7 @@ unwind_jump:;
755801
}
756802

757803
ENTRY(MP_BC_RETURN_VALUE):
804+
MARK_EXC_IP_SELECTIVE();
758805
unwind_return:
759806
while (exc_sp >= exc_stack) {
760807
if (MP_TAGPTR_TAG1(exc_sp->val_sp)) {
@@ -778,6 +825,7 @@ unwind_jump:;
778825
return MP_VM_RETURN_NORMAL;
779826

780827
ENTRY(MP_BC_RAISE_VARARGS): {
828+
MARK_EXC_IP_SELECTIVE();
781829
mp_uint_t unum = *ip++;
782830
mp_obj_t obj;
783831
assert(unum <= 1);
@@ -810,6 +858,7 @@ unwind_jump:;
810858
return MP_VM_RETURN_YIELD;
811859

812860
ENTRY(MP_BC_YIELD_FROM): {
861+
MARK_EXC_IP_SELECTIVE();
813862
//#define EXC_MATCH(exc, type) MP_OBJ_IS_TYPE(exc, type)
814863
#define EXC_MATCH(exc, type) mp_obj_exception_match(exc, type)
815864
#define GENERATOR_EXIT_IF_NEEDED(t) if (t != MP_OBJ_NULL && EXC_MATCH(t, &mp_type_GeneratorExit)) { RAISE(t); }
@@ -862,20 +911,23 @@ unwind_jump:;
862911
}
863912

864913
ENTRY(MP_BC_IMPORT_NAME): {
914+
MARK_EXC_IP_SELECTIVE();
865915
DECODE_QSTR;
866916
mp_obj_t obj = POP();
867917
SET_TOP(mp_import_name(qst, obj, TOP()));
868918
DISPATCH();
869919
}
870920

871921
ENTRY(MP_BC_IMPORT_FROM): {
922+
MARK_EXC_IP_SELECTIVE();
872923
DECODE_QSTR;
873924
mp_obj_t obj = mp_import_from(TOP(), qst);
874925
PUSH(obj);
875926
DISPATCH();
876927
}
877928

878929
ENTRY(MP_BC_IMPORT_STAR):
930+
MARK_EXC_IP_SELECTIVE();
879931
mp_import_all(POP());
880932
DISPATCH();
881933

@@ -893,17 +945,20 @@ unwind_jump:;
893945
DISPATCH();
894946

895947
ENTRY(MP_BC_UNARY_OP_MULTI):
948+
MARK_EXC_IP_SELECTIVE();
896949
SET_TOP(mp_unary_op(ip[-1] - MP_BC_UNARY_OP_MULTI, TOP()));
897950
DISPATCH();
898951

899952
ENTRY(MP_BC_BINARY_OP_MULTI): {
953+
MARK_EXC_IP_SELECTIVE();
900954
mp_obj_t rhs = POP();
901955
mp_obj_t lhs = TOP();
902956
SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs));
903957
DISPATCH();
904958
}
905959

906960
ENTRY_DEFAULT:
961+
MARK_EXC_IP_SELECTIVE();
907962
#else
908963
ENTRY_DEFAULT:
909964
if (ip[-1] < MP_BC_LOAD_CONST_SMALL_INT_MULTI + 64) {
@@ -938,6 +993,7 @@ unwind_jump:;
938993

939994
pending_exception_check:
940995
if (mp_pending_exception != MP_OBJ_NULL) {
996+
MARK_EXC_IP_SELECTIVE();
941997
mp_obj_t obj = mp_pending_exception;
942998
mp_pending_exception = MP_OBJ_NULL;
943999
RAISE(obj);

0 commit comments

Comments
 (0)