@@ -2482,29 +2482,23 @@ context_used_is_mrgctx (MonoCompile *cfg, int context_used)
2482
2482
/*
2483
2483
* emit_get_rgctx:
2484
2484
*
2485
- * Emit IR to return either the this pointer for instance method,
2486
- * or the mrgctx for static methods.
2485
+ * Emit IR to return either the vtable or the mrgctx.
2487
2486
*/
2488
2487
static MonoInst *
2489
2488
emit_get_rgctx (MonoCompile * cfg , int context_used )
2490
2489
{
2491
- MonoInst * this_ins = NULL ;
2492
2490
MonoMethod * method = cfg -> method ;
2493
2491
2494
2492
g_assert (cfg -> gshared );
2495
2493
2496
- if (!(method -> flags & METHOD_ATTRIBUTE_STATIC ) &&
2497
- !(context_used & MONO_GENERIC_CONTEXT_USED_METHOD ) &&
2498
- !m_class_is_valuetype (method -> klass ))
2499
- EMIT_NEW_VARLOAD (cfg , this_ins , cfg -> this_arg , mono_get_object_type ());
2500
-
2494
+ /* Data whose context contains method type vars is stored in the mrgctx */
2501
2495
if (context_used_is_mrgctx (cfg , context_used )) {
2502
2496
MonoInst * mrgctx_loc , * mrgctx_var ;
2503
2497
2504
- if (!mini_method_is_default_method (method )) {
2505
- g_assert (!this_ins );
2498
+ g_assert (cfg -> rgctx_access == MONO_RGCTX_ACCESS_MRGCTX );
2499
+
2500
+ if (!mini_method_is_default_method (method ))
2506
2501
g_assert (method -> is_inflated && mono_method_get_context (method )-> method_inst );
2507
- }
2508
2502
2509
2503
if (cfg -> llvm_only ) {
2510
2504
mrgctx_var = mono_get_mrgctx_var (cfg );
@@ -2515,10 +2509,34 @@ emit_get_rgctx (MonoCompile *cfg, int context_used)
2515
2509
EMIT_NEW_TEMPLOAD (cfg , mrgctx_var , mrgctx_loc -> inst_c0 );
2516
2510
}
2517
2511
return mrgctx_var ;
2518
- } else if (method -> flags & METHOD_ATTRIBUTE_STATIC || m_class_is_valuetype (method -> klass )) {
2512
+ }
2513
+
2514
+ /*
2515
+ * The rest of the entries are stored in vtable->runtime_generic_context so
2516
+ * have to return a vtable.
2517
+ */
2518
+ if (cfg -> rgctx_access == MONO_RGCTX_ACCESS_MRGCTX ) {
2519
+ MonoInst * mrgctx_loc , * mrgctx_var , * vtable_var ;
2520
+ int vtable_reg ;
2521
+
2522
+ /* We are passed an mrgctx, return mrgctx->class_vtable */
2523
+
2524
+ if (cfg -> llvm_only ) {
2525
+ mrgctx_var = mono_get_mrgctx_var (cfg );
2526
+ } else {
2527
+ mrgctx_loc = mono_get_mrgctx_var (cfg );
2528
+ g_assert (mrgctx_loc -> flags & MONO_INST_VOLATILE );
2529
+ EMIT_NEW_TEMPLOAD (cfg , mrgctx_var , mrgctx_loc -> inst_c0 );
2530
+ }
2531
+
2532
+ vtable_reg = alloc_preg (cfg );
2533
+ EMIT_NEW_LOAD_MEMBASE (cfg , vtable_var , OP_LOAD_MEMBASE , vtable_reg , mrgctx_var -> dreg , MONO_STRUCT_OFFSET (MonoMethodRuntimeGenericContext , class_vtable ));
2534
+ vtable_var -> type = STACK_PTR ;
2535
+ return vtable_var ;
2536
+ } else if (cfg -> rgctx_access == MONO_RGCTX_ACCESS_VTABLE ) {
2519
2537
MonoInst * vtable_loc , * vtable_var ;
2520
2538
2521
- g_assert (! this_ins );
2539
+ /* We are passed a vtable, return it */
2522
2540
2523
2541
if (cfg -> llvm_only ) {
2524
2542
vtable_var = mono_get_vtable_var (cfg );
@@ -2527,20 +2545,15 @@ emit_get_rgctx (MonoCompile *cfg, int context_used)
2527
2545
g_assert (vtable_loc -> flags & MONO_INST_VOLATILE );
2528
2546
EMIT_NEW_TEMPLOAD (cfg , vtable_var , vtable_loc -> inst_c0 );
2529
2547
}
2530
-
2531
- if (method -> is_inflated && mono_method_get_context (method )-> method_inst ) {
2532
- MonoInst * mrgctx_var = vtable_var ;
2533
- int vtable_reg ;
2534
-
2535
- vtable_reg = alloc_preg (cfg );
2536
- EMIT_NEW_LOAD_MEMBASE (cfg , vtable_var , OP_LOAD_MEMBASE , vtable_reg , mrgctx_var -> dreg , MONO_STRUCT_OFFSET (MonoMethodRuntimeGenericContext , class_vtable ));
2537
- vtable_var -> type = STACK_PTR ;
2538
- }
2539
-
2548
+ vtable_var -> type = STACK_PTR ;
2540
2549
return vtable_var ;
2541
2550
} else {
2542
- MonoInst * ins ;
2551
+ MonoInst * ins , * this_ins ;
2543
2552
int vtable_reg ;
2553
+
2554
+ /* We are passed a this pointer, return this->vtable */
2555
+
2556
+ EMIT_NEW_VARLOAD (cfg , this_ins , cfg -> this_arg , mono_get_object_type ());
2544
2557
2545
2558
vtable_reg = alloc_preg (cfg );
2546
2559
EMIT_NEW_LOAD_MEMBASE (cfg , ins , OP_LOAD_MEMBASE , vtable_reg , this_ins -> dreg , MONO_STRUCT_OFFSET (MonoObject , vtable ));
@@ -2675,12 +2688,13 @@ emit_rgctx_fetch_inline (MonoCompile *cfg, MonoInst *rgctx, MonoJumpInfoRgctxEnt
2675
2688
/*
2676
2689
* emit_rgctx_fetch:
2677
2690
*
2678
- * Emit IR to load the value of the rgctx entry ENTRY from the rgctx
2679
- * given by RGCTX.
2691
+ * Emit IR to load the value of the rgctx entry ENTRY from the rgctx.
2680
2692
*/
2681
2693
static MonoInst *
2682
- emit_rgctx_fetch (MonoCompile * cfg , MonoInst * rgctx , MonoJumpInfoRgctxEntry * entry )
2694
+ emit_rgctx_fetch (MonoCompile * cfg , int context_used , MonoJumpInfoRgctxEntry * entry )
2683
2695
{
2696
+ MonoInst * rgctx = emit_get_rgctx (cfg , context_used );
2697
+
2684
2698
if (cfg -> llvm_only )
2685
2699
return emit_rgctx_fetch_inline (cfg , rgctx , entry );
2686
2700
else
@@ -2704,25 +2718,32 @@ mini_emit_get_rgctx_klass (MonoCompile *cfg, int context_used,
2704
2718
case MONO_RGCTX_INFO_KLASS :
2705
2719
EMIT_NEW_CLASSCONST (cfg , ins , klass );
2706
2720
return ins ;
2721
+ case MONO_RGCTX_INFO_VTABLE : {
2722
+ MonoVTable * vtable = mono_class_vtable_checked (klass , cfg -> error );
2723
+ CHECK_CFG_ERROR ;
2724
+ EMIT_NEW_VTABLECONST (cfg , ins , vtable );
2725
+ return ins ;
2726
+ }
2707
2727
default :
2708
2728
g_assert_not_reached ();
2709
2729
}
2710
2730
}
2711
2731
2712
2732
MonoJumpInfoRgctxEntry * entry = mono_patch_info_rgctx_entry_new (cfg -> mempool , cfg -> method , context_used_is_mrgctx (cfg , context_used ), MONO_PATCH_INFO_CLASS , klass , rgctx_type );
2713
- MonoInst * rgctx = emit_get_rgctx (cfg , context_used );
2714
2733
2715
- return emit_rgctx_fetch (cfg , rgctx , entry );
2734
+ return emit_rgctx_fetch (cfg , context_used , entry );
2735
+
2736
+ mono_error_exit :
2737
+ return NULL ;
2716
2738
}
2717
2739
2718
2740
static MonoInst *
2719
2741
emit_get_rgctx_sig (MonoCompile * cfg , int context_used ,
2720
2742
MonoMethodSignature * sig , MonoRgctxInfoType rgctx_type )
2721
2743
{
2722
2744
MonoJumpInfoRgctxEntry * entry = mono_patch_info_rgctx_entry_new (cfg -> mempool , cfg -> method , context_used_is_mrgctx (cfg , context_used ), MONO_PATCH_INFO_SIGNATURE , sig , rgctx_type );
2723
- MonoInst * rgctx = emit_get_rgctx (cfg , context_used );
2724
2745
2725
- return emit_rgctx_fetch (cfg , rgctx , entry );
2746
+ return emit_rgctx_fetch (cfg , context_used , entry );
2726
2747
}
2727
2748
2728
2749
static MonoInst *
@@ -2731,16 +2752,14 @@ emit_get_rgctx_gsharedvt_call (MonoCompile *cfg, int context_used,
2731
2752
{
2732
2753
MonoJumpInfoGSharedVtCall * call_info ;
2733
2754
MonoJumpInfoRgctxEntry * entry ;
2734
- MonoInst * rgctx ;
2735
2755
2736
2756
call_info = (MonoJumpInfoGSharedVtCall * )mono_mempool_alloc0 (cfg -> mempool , sizeof (MonoJumpInfoGSharedVtCall ));
2737
2757
call_info -> sig = sig ;
2738
2758
call_info -> method = cmethod ;
2739
2759
2740
2760
entry = mono_patch_info_rgctx_entry_new (cfg -> mempool , cfg -> method , context_used_is_mrgctx (cfg , context_used ), MONO_PATCH_INFO_GSHAREDVT_CALL , call_info , rgctx_type );
2741
- rgctx = emit_get_rgctx (cfg , context_used );
2742
2761
2743
- return emit_rgctx_fetch (cfg , rgctx , entry );
2762
+ return emit_rgctx_fetch (cfg , context_used , entry );
2744
2763
}
2745
2764
2746
2765
/*
@@ -2754,29 +2773,25 @@ emit_get_rgctx_virt_method (MonoCompile *cfg, int context_used,
2754
2773
{
2755
2774
MonoJumpInfoVirtMethod * info ;
2756
2775
MonoJumpInfoRgctxEntry * entry ;
2757
- MonoInst * rgctx ;
2758
2776
2759
2777
info = (MonoJumpInfoVirtMethod * )mono_mempool_alloc0 (cfg -> mempool , sizeof (MonoJumpInfoVirtMethod ));
2760
2778
info -> klass = klass ;
2761
2779
info -> method = virt_method ;
2762
2780
2763
2781
entry = mono_patch_info_rgctx_entry_new (cfg -> mempool , cfg -> method , context_used_is_mrgctx (cfg , context_used ), MONO_PATCH_INFO_VIRT_METHOD , info , rgctx_type );
2764
- rgctx = emit_get_rgctx (cfg , context_used );
2765
2782
2766
- return emit_rgctx_fetch (cfg , rgctx , entry );
2783
+ return emit_rgctx_fetch (cfg , context_used , entry );
2767
2784
}
2768
2785
2769
2786
static MonoInst *
2770
2787
emit_get_rgctx_gsharedvt_method (MonoCompile * cfg , int context_used ,
2771
2788
MonoMethod * cmethod , MonoGSharedVtMethodInfo * info )
2772
2789
{
2773
2790
MonoJumpInfoRgctxEntry * entry ;
2774
- MonoInst * rgctx ;
2775
2791
2776
2792
entry = mono_patch_info_rgctx_entry_new (cfg -> mempool , cfg -> method , context_used_is_mrgctx (cfg , context_used ), MONO_PATCH_INFO_GSHAREDVT_METHOD , info , MONO_RGCTX_INFO_METHOD_GSHAREDVT_INFO );
2777
- rgctx = emit_get_rgctx (cfg , context_used );
2778
2793
2779
- return emit_rgctx_fetch (cfg , rgctx , entry );
2794
+ return emit_rgctx_fetch (cfg , context_used , entry );
2780
2795
}
2781
2796
2782
2797
/*
@@ -2810,9 +2825,8 @@ emit_get_rgctx_method (MonoCompile *cfg, int context_used,
2810
2825
}
2811
2826
} else {
2812
2827
MonoJumpInfoRgctxEntry * entry = mono_patch_info_rgctx_entry_new (cfg -> mempool , cfg -> method , context_used_is_mrgctx (cfg , context_used ), MONO_PATCH_INFO_METHODCONST , cmethod , rgctx_type );
2813
- MonoInst * rgctx = emit_get_rgctx (cfg , context_used );
2814
2828
2815
- return emit_rgctx_fetch (cfg , rgctx , entry );
2829
+ return emit_rgctx_fetch (cfg , context_used , entry );
2816
2830
}
2817
2831
}
2818
2832
@@ -2821,9 +2835,8 @@ emit_get_rgctx_field (MonoCompile *cfg, int context_used,
2821
2835
MonoClassField * field , MonoRgctxInfoType rgctx_type )
2822
2836
{
2823
2837
MonoJumpInfoRgctxEntry * entry = mono_patch_info_rgctx_entry_new (cfg -> mempool , cfg -> method , context_used_is_mrgctx (cfg , context_used ), MONO_PATCH_INFO_FIELD , field , rgctx_type );
2824
- MonoInst * rgctx = emit_get_rgctx (cfg , context_used );
2825
2838
2826
- return emit_rgctx_fetch (cfg , rgctx , entry );
2839
+ return emit_rgctx_fetch (cfg , context_used , entry );
2827
2840
}
2828
2841
2829
2842
MonoInst *
@@ -3522,20 +3535,17 @@ emit_get_rgctx_dele_tramp (MonoCompile *cfg, int context_used,
3522
3535
{
3523
3536
MonoDelegateClassMethodPair * info ;
3524
3537
MonoJumpInfoRgctxEntry * entry ;
3525
- MonoInst * rgctx ;
3526
3538
3527
3539
info = (MonoDelegateClassMethodPair * )mono_mempool_alloc0 (cfg -> mempool , sizeof (MonoDelegateClassMethodPair ));
3528
3540
info -> klass = klass ;
3529
3541
info -> method = virt_method ;
3530
3542
info -> is_virtual = _virtual ;
3531
3543
3532
3544
entry = mono_patch_info_rgctx_entry_new (cfg -> mempool , cfg -> method , context_used_is_mrgctx (cfg , context_used ), MONO_PATCH_INFO_DELEGATE_TRAMPOLINE , info , rgctx_type );
3533
- rgctx = emit_get_rgctx (cfg , context_used );
3534
3545
3535
- return emit_rgctx_fetch (cfg , rgctx , entry );
3546
+ return emit_rgctx_fetch (cfg , context_used , entry );
3536
3547
}
3537
3548
3538
-
3539
3549
/*
3540
3550
* Returns NULL and set the cfg exception on error.
3541
3551
*/
@@ -5563,25 +5573,23 @@ handle_ctor_call (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fs
5563
5573
{
5564
5574
MonoInst * vtable_arg = NULL , * callvirt_this_arg = NULL , * ins ;
5565
5575
5566
- if (m_class_is_valuetype (cmethod -> klass ) && mono_class_generic_sharing_enabled (cmethod -> klass ) &&
5567
- mono_method_is_generic_sharable (cmethod , TRUE)) {
5568
- if (cmethod -> is_inflated && mono_method_get_context (cmethod )-> method_inst ) {
5576
+ if (mono_class_generic_sharing_enabled (cmethod -> klass ) && mono_method_is_generic_sharable (cmethod , TRUE)) {
5577
+ MonoRgctxAccess access = mini_get_rgctx_access_for_method (cmethod );
5578
+
5579
+ if (access == MONO_RGCTX_ACCESS_MRGCTX ) {
5569
5580
mono_class_vtable_checked (cmethod -> klass , cfg -> error );
5570
5581
CHECK_CFG_ERROR ;
5571
5582
CHECK_TYPELOAD (cmethod -> klass );
5572
5583
5573
5584
vtable_arg = emit_get_rgctx_method (cfg , context_used ,
5574
5585
cmethod , MONO_RGCTX_INFO_METHOD_RGCTX );
5586
+ } else if (access == MONO_RGCTX_ACCESS_VTABLE ) {
5587
+ vtable_arg = mini_emit_get_rgctx_klass (cfg , context_used ,
5588
+ cmethod -> klass , MONO_RGCTX_INFO_VTABLE );
5589
+ CHECK_CFG_ERROR ;
5590
+ CHECK_TYPELOAD (cmethod -> klass );
5575
5591
} else {
5576
- if (context_used ) {
5577
- vtable_arg = mini_emit_get_rgctx_klass (cfg , context_used ,
5578
- cmethod -> klass , MONO_RGCTX_INFO_VTABLE );
5579
- } else {
5580
- MonoVTable * vtable = mono_class_vtable_checked (cmethod -> klass , cfg -> error );
5581
- CHECK_CFG_ERROR ;
5582
- CHECK_TYPELOAD (cmethod -> klass );
5583
- EMIT_NEW_VTABLECONST (cfg , vtable_arg , vtable );
5584
- }
5592
+ g_assert (access == MONO_RGCTX_ACCESS_THIS );
5585
5593
}
5586
5594
}
5587
5595
0 commit comments