@@ -4803,6 +4803,15 @@ interp_emit_sfld_access (TransformData *td, MonoClassField *field, MonoClass *fi
4803
4803
}
4804
4804
}
4805
4805
4806
+ static MonoClass *
4807
+ get_class_from_token (MonoGenericContext * generic_context , MonoMethod * cur_method , uint32_t token )
4808
+ {
4809
+ if (cur_method -> wrapper_type != MONO_WRAPPER_NONE )
4810
+ return (MonoClass * )mono_method_get_wrapper_data (cur_method , token );
4811
+ else
4812
+ return mini_get_class (cur_method , token , generic_context );
4813
+ }
4814
+
4806
4815
static gboolean
4807
4816
interp_handle_box_patterns (TransformData * td , MonoClass * box_class , const unsigned char * end , MonoImage * image , MonoGenericContext * generic_context , MonoError * error )
4808
4817
{
@@ -4828,24 +4837,93 @@ interp_handle_box_patterns (TransformData *td, MonoClass *box_class, const unsig
4828
4837
return TRUE;
4829
4838
}
4830
4839
if (m_class_is_byreflike (box_class )) {
4831
- if (* next_ip == CEE_BRTRUE || * next_ip == CEE_BRTRUE_S || * next_ip == CEE_BRFALSE || * next_ip == CEE_BRFALSE_S ) {
4832
- // replace
4833
- // box ByRefLike
4834
- // brtrue/brfalse
4835
- //
4836
- // by
4837
- //
4838
- // ldc.i4.s 1
4839
- // brtrue/brfalse
4840
- td -> sp -- ;
4841
- interp_add_ins (td , MINT_LDC_I4_S );
4842
- td -> last_ins -> data [0 ] = (guint16 ) 1 ;
4843
- push_simple_type (td , STACK_TYPE_I4 );
4844
- interp_ins_set_dreg (td -> last_ins , td -> sp [-1 ].var );
4845
- td -> ip += 5 ;
4846
- return TRUE;
4840
+ if (* next_ip == CEE_BRTRUE || * next_ip == CEE_BRTRUE_S || * next_ip == CEE_BRFALSE || * next_ip == CEE_BRFALSE_S ) {
4841
+ // replace
4842
+ // box ByRefLike
4843
+ // [brtrue/brfalse]
4844
+ //
4845
+ // by
4846
+ //
4847
+ // ldc.i4.s 1
4848
+ // [brtrue/brfalse]
4849
+ td -> sp -- ;
4850
+ interp_add_ins (td , MINT_LDC_I4_S );
4851
+ td -> last_ins -> data [0 ] = (guint16 ) 1 ;
4852
+ push_simple_type (td , STACK_TYPE_I4 );
4853
+ interp_ins_set_dreg (td -> last_ins , td -> sp [-1 ].var );
4854
+ td -> ip += 5 ;
4855
+ // skip over box, continue with the branch opcode
4856
+ return TRUE;
4857
+ }
4858
+ if (* next_ip == CEE_ISINST ) {
4859
+ // box !!T
4860
+ // isinst S
4861
+ // [brtrue/brfalse]
4862
+ //
4863
+ // turns into
4864
+ // ldc.i4.s (0 or 1)
4865
+ // [brtrue/brfalse]
4866
+
4867
+ // and
4868
+
4869
+ // box !!T
4870
+ // isinst S
4871
+ // unbox.any S
4872
+ //
4873
+ // turns into
4874
+ // nop
4875
+ // -or-
4876
+ // ldnull
4877
+ // cknull
4878
+ const unsigned char * second_ip = next_ip + 5 ;
4879
+ if (second_ip >= end || !interp_ip_in_cbb (td , GPTRDIFF_TO_INT (second_ip - td -> il_code ))) {
4880
+ return FALSE;
4881
+ }
4882
+
4883
+ uint32_t isinst_token = read32 (next_ip + 1 );
4884
+ MonoClass * isinst_klass = get_class_from_token (generic_context , method , isinst_token );
4885
+
4886
+ CHECK_TYPELOAD (isinst_klass );
4887
+
4888
+ gboolean isinst = mono_class_is_assignable_from_internal (isinst_klass , box_class );
4889
+
4890
+ if (* second_ip == CEE_BRTRUE || * second_ip == CEE_BRTRUE_S || * second_ip == CEE_BRFALSE || * second_ip == CEE_BRFALSE_S ) {
4891
+ td -> sp -- ;
4892
+ interp_add_ins (td , MINT_LDC_I4_S );
4893
+ td -> last_ins -> data [0 ] = (guint16 ) (isinst ? 1 : 0 );
4894
+ push_simple_type (td , STACK_TYPE_I4 );
4895
+ interp_ins_set_dreg (td -> last_ins , td -> sp [-1 ].var );
4896
+ td -> ip = next_ip + 5 ;
4897
+ // skip over the box and isinst opcodes, continue with the branch opcode
4898
+ return TRUE;
4899
+ }
4900
+ if (* second_ip == CEE_UNBOX_ANY ) {
4901
+ uint32_t unbox_any_token = read32 (second_ip + 1 );
4902
+ MonoClass * unbox_klass = get_class_from_token (generic_context , method , unbox_any_token );
4903
+ CHECK_TYPELOAD (unbox_klass );
4904
+ if (unbox_klass == isinst_klass ) {
4905
+ if (isinst ) {
4906
+ // leave the original value unchanged on the stack
4907
+ interp_add_ins (td , MINT_NOP );
4908
+ } else {
4909
+ // pop the original value, throw a NullReferenceException
4910
+ td -> sp -- ;
4911
+ interp_add_ins (td , MINT_LDNULL );
4912
+ push_simple_type (td , STACK_TYPE_O );
4913
+ interp_ins_set_dreg (td -> last_ins , td -> sp [-1 ].var );
4914
+ interp_add_ins (td , MINT_CKNULL );
4915
+ interp_ins_set_sreg (td -> last_ins , td -> sp -> var );
4916
+ set_simple_type_and_var (td , td -> sp , td -> sp -> type );
4917
+ interp_ins_set_dreg (td -> last_ins , td -> sp -> var );
4918
+ }
4919
+ td -> ip = second_ip + 5 ;
4920
+ // skip over all three opcodes, continue with the next opcode;
4921
+ return TRUE;
4922
+ }
4923
+ }
4847
4924
}
4848
4925
}
4926
+ exit :
4849
4927
return FALSE;
4850
4928
}
4851
4929
0 commit comments