@@ -376,6 +376,74 @@ __type_propagate_TYPE_OVERWRITE(
376
376
}
377
377
}
378
378
379
+ // src and dst are assumed to already be within the type context
380
+ static void
381
+ __type_propagate_TYPE_SWAP (
382
+ _PyTier2TypeContext * type_context ,
383
+ _Py_TYPENODE_t * src , _Py_TYPENODE_t * dst )
384
+ {
385
+ // Check if they are the same tree
386
+ _Py_TYPENODE_t * srcrootref = src ;
387
+ _Py_TYPENODE_t * dstrootref = dst ;
388
+ uintptr_t dsttag = _Py_TYPENODE_GET_TAG (* dst );
389
+ uintptr_t srctag = _Py_TYPENODE_GET_TAG (* src );
390
+ switch (dsttag ) {
391
+ case TYPE_REF : dstrootref = __typenode_get_rootptr (* dst );
392
+ case TYPE_ROOT :
393
+ switch (srctag ) {
394
+ case TYPE_REF : srcrootref = __typenode_get_rootptr (* src );
395
+ case TYPE_ROOT :
396
+ if (srcrootref == dstrootref ) {
397
+ // Same tree, no point swapping
398
+ return ;
399
+ }
400
+ break ;
401
+ default :
402
+ Py_UNREACHABLE ();
403
+ }
404
+ break ;
405
+ default :
406
+ Py_UNREACHABLE ();
407
+ }
408
+
409
+ // src and dst are different tree,
410
+ // Make all children of src be children of dst and vice versa
411
+
412
+ _Py_TYPENODE_t src_child_test = _Py_TYPENODE_MAKE_REF (
413
+ _Py_TYPENODE_CLEAR_TAG ((_Py_TYPENODE_t )src ));
414
+ _Py_TYPENODE_t dst_child_test = _Py_TYPENODE_MAKE_REF (
415
+ _Py_TYPENODE_CLEAR_TAG ((_Py_TYPENODE_t )dst ));
416
+
417
+ // Search locals for children
418
+ int nlocals = type_context -> type_locals_len ;
419
+ for (int i = 0 ; i < nlocals ; i ++ ) {
420
+ _Py_TYPENODE_t * node_ptr = & (type_context -> type_locals [i ]);
421
+ if (* node_ptr == src_child_test ) {
422
+ * node_ptr = dst_child_test ;
423
+ }
424
+ else if (* node_ptr == dst_child_test ) {
425
+ * node_ptr = src_child_test ;
426
+ }
427
+ }
428
+
429
+ // Search stack for children
430
+ int nstack = type_context -> type_stack_len ;
431
+ for (int i = 0 ; i < nstack ; i ++ ) {
432
+ _Py_TYPENODE_t * node_ptr = & (type_context -> type_stack [i ]);
433
+ if (* node_ptr == src_child_test ) {
434
+ * node_ptr = dst_child_test ;
435
+ }
436
+ else if (* node_ptr == dst_child_test ) {
437
+ * node_ptr = src_child_test ;
438
+ }
439
+ }
440
+
441
+ // Finally, actually swap the nodes
442
+ * src ^= * dst ;
443
+ * dst ^= * src ;
444
+ * src ^= * dst ;
445
+ }
446
+
379
447
static void
380
448
__type_stack_shrink (_Py_TYPENODE_t * * type_stackptr , int idx )
381
449
{
@@ -489,6 +557,7 @@ type_propagate(
489
557
490
558
#define TYPE_SET (src , dst , flag ) __type_propagate_TYPE_SET((src), (dst), (flag))
491
559
#define TYPE_OVERWRITE (src , dst , flag ) __type_propagate_TYPE_OVERWRITE(type_context, (src), (dst), (flag))
560
+ #define TYPE_SWAP (src , dst ) __type_propagate_TYPE_SWAP(type_context, (src), (dst))
492
561
493
562
#define STACK_GROW (idx ) *type_stackptr += (idx)
494
563
@@ -504,8 +573,18 @@ type_propagate(
504
573
505
574
switch (opcode ) {
506
575
#include "tier2_typepropagator.c.h"
576
+ TARGET (SWAP ) {
577
+ _Py_TYPENODE_t * top = TYPESTACK_PEEK (1 );
578
+ _Py_TYPENODE_t * bottom = TYPESTACK_PEEK (2 + (oparg - 2 ));
579
+ TYPE_SWAP (top , bottom );
580
+ break ;
581
+ }
507
582
default :
583
+ #ifdef Py_DEBUG
584
+ fprintf (stderr , "Unsupported opcode in type propagator: %s : %d\n" , _PyOpcode_OpName [opcode ], oparg );
585
+ #else
508
586
fprintf (stderr , "Unsupported opcode in type propagator: %d\n" , opcode );
587
+ #endif
509
588
Py_UNREACHABLE ();
510
589
}
511
590
0 commit comments