Skip to content

Commit d586ae2

Browse files
committed
handle box;isinst;{brtrue|brfalse|unbox.any} IL patterns
1 parent faa8e79 commit d586ae2

File tree

1 file changed

+94
-16
lines changed

1 file changed

+94
-16
lines changed

src/mono/mono/mini/interp/transform.c

Lines changed: 94 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4803,6 +4803,15 @@ interp_emit_sfld_access (TransformData *td, MonoClassField *field, MonoClass *fi
48034803
}
48044804
}
48054805

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+
48064815
static gboolean
48074816
interp_handle_box_patterns (TransformData *td, MonoClass *box_class, const unsigned char *end, MonoImage *image, MonoGenericContext *generic_context, MonoError *error)
48084817
{
@@ -4828,24 +4837,93 @@ interp_handle_box_patterns (TransformData *td, MonoClass *box_class, const unsig
48284837
return TRUE;
48294838
}
48304839
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+
}
48474924
}
48484925
}
4926+
exit:
48494927
return FALSE;
48504928
}
48514929

0 commit comments

Comments
 (0)