Skip to content

Commit

Permalink
[mono] Fix a regression caused by 9ddd58a.
Browse files Browse the repository at this point in the history
  • Loading branch information
vargaz committed Dec 24, 2021
1 parent 2a48729 commit edbe39f
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 18 deletions.
2 changes: 2 additions & 0 deletions src/mono/mono/metadata/jit-icall-reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ MONO_JIT_ICALL (__emul_ldiv_un) \
MONO_JIT_ICALL (__emul_lmul) \
MONO_JIT_ICALL (__emul_lmul_ovf) \
MONO_JIT_ICALL (__emul_lmul_ovf_un) \
MONO_JIT_ICALL (__emul_lmul_ovf_un_oom) \
MONO_JIT_ICALL (__emul_lrem) \
MONO_JIT_ICALL (__emul_lrem_un) \
MONO_JIT_ICALL (__emul_lshl) \
Expand All @@ -108,6 +109,7 @@ MONO_JIT_ICALL (__emul_op_idiv_un) \
MONO_JIT_ICALL (__emul_op_imul) \
MONO_JIT_ICALL (__emul_op_imul_ovf) \
MONO_JIT_ICALL (__emul_op_imul_ovf_un) \
MONO_JIT_ICALL (__emul_op_imul_ovf_un_oom) \
MONO_JIT_ICALL (__emul_op_irem) \
MONO_JIT_ICALL (__emul_op_irem_un) \
MONO_JIT_ICALL (__emul_rconv_to_i8) \
Expand Down
49 changes: 49 additions & 0 deletions src/mono/mono/mini/jit-icalls.c
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,40 @@ mono_llmult_ovf_un (guint64 a, guint64 b)
return 0;
}

guint64
mono_llmult_ovf_un_oom (guint64 a, guint64 b)
{
guint32 al = a;
guint32 ah = a >> 32;
guint32 bl = b;
guint32 bh = b >> 32;
guint64 res, t1;

// fixme: this is incredible slow

if (ah && bh)
goto raise_exception;

res = (guint64)al * (guint64)bl;

t1 = (guint64)ah * (guint64)bl + (guint64)al * (guint64)bh;

if (t1 > 0xffffffff)
goto raise_exception;

res += ((guint64)t1) << 32;

return res;

raise_exception:
{
ERROR_DECL (error);
mono_error_set_out_of_memory (error, "");
mono_error_set_pending_exception (error);
}
return 0;
}

guint64
mono_llmult_ovf (gint64 a, gint64 b)
{
Expand Down Expand Up @@ -521,6 +555,21 @@ mono_imul_ovf_un (guint32 a, guint32 b)

return res;
}

gint32
mono_imul_ovf_un_oom (guint32 a, guint32 b)
{
const guint64 res = (guint64)a * (guint64)b;

if (res >> 32) {
ERROR_DECL (error);
mono_error_set_out_of_memory (error, "");
mono_error_set_pending_exception (error);
return 0;
}

return res;
}
#endif

#if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_SOFT_FLOAT_FALLBACK)
Expand Down
4 changes: 4 additions & 0 deletions src/mono/mono/mini/jit-icalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ ICALL_EXPORT gint64 mono_llmult (gint64 a, gint64 b);

ICALL_EXPORT guint64 mono_llmult_ovf_un (guint64 a, guint64 b);

ICALL_EXPORT guint64 mono_llmult_ovf_un_oom (guint64 a, guint64 b);

ICALL_EXPORT guint64 mono_llmult_ovf (gint64 a, gint64 b);

ICALL_EXPORT gint32 mono_idiv (gint32 a, gint32 b);
Expand All @@ -37,6 +39,8 @@ ICALL_EXPORT gint32 mono_imul_ovf (gint32 a, gint32 b);

ICALL_EXPORT gint32 mono_imul_ovf_un (guint32 a, guint32 b);

ICALL_EXPORT gint32 mono_imul_ovf_un_oom (guint32 a, guint32 b);

ICALL_EXPORT double mono_fdiv (double a, double b);

ICALL_EXPORT gint64 mono_lldiv (gint64 a, gint64 b);
Expand Down
47 changes: 31 additions & 16 deletions src/mono/mono/mini/method-to-ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -517,21 +517,6 @@ add_widen_op (MonoCompile *cfg, MonoInst *ins, MonoInst **arg1_ref, MonoInst **a
#endif
}

#define ADD_BINOP(op) do { \
MONO_INST_NEW (cfg, ins, (op)); \
sp -= 2; \
ins->sreg1 = sp [0]->dreg; \
ins->sreg2 = sp [1]->dreg; \
type_from_op (cfg, ins, sp [0], sp [1]); \
CHECK_TYPE (ins); \
if (ovf_exc) ins->inst_exc_name = ovf_exc; else ins->inst_exc_name = "OverflowException"; ovf_exc = NULL; \
/* Have to insert a widening op */ \
add_widen_op (cfg, ins, &sp [0], &sp [1]); \
ins->dreg = alloc_dreg ((cfg), (MonoStackType)(ins)->type); \
MONO_ADD_INS ((cfg)->cbb, (ins)); \
*sp++ = mono_decompose_opcode ((cfg), (ins)); \
} while (0)

#define ADD_UNOP(op) do { \
MONO_INST_NEW (cfg, ins, (op)); \
sp--; \
Expand Down Expand Up @@ -8674,7 +8659,37 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
case MONO_CEE_MUL_OVF_UN:
case MONO_CEE_SUB_OVF:
case MONO_CEE_SUB_OVF_UN:
ADD_BINOP (il_op);
MONO_INST_NEW (cfg, ins, il_op);
sp -= 2;
ins->sreg1 = sp [0]->dreg;
ins->sreg2 = sp [1]->dreg;
type_from_op (cfg, ins, sp [0], sp [1]);
CHECK_TYPE (ins);
if (ovf_exc)
ins->inst_exc_name = ovf_exc;
else
ins->inst_exc_name = "OverflowException";
/* Have to insert a widening op */
add_widen_op (cfg, ins, &sp [0], &sp [1]);
ins->dreg = alloc_dreg (cfg, (MonoStackType)(ins)->type);
MONO_ADD_INS ((cfg)->cbb, ins);
/* The opcode might be emulated, so need to special case this */
if (ovf_exc && mono_find_jit_opcode_emulation (ins->opcode)) {
switch (ins->opcode) {
case OP_IMUL_OVF_UN:
/* This opcode is just a placeholder, it will be emulated also */
ins->opcode = OP_IMUL_OVF_UN_OOM;
break;
case OP_LMUL_OVF_UN:
/* This opcode is just a placeholder, it will be emulated also */
ins->opcode = OP_LMUL_OVF_UN_OOM;
break;
default:
g_assert_not_reached ();
}
}
ovf_exc = NULL;
*sp++ = mono_decompose_opcode (cfg, ins);
break;
case MONO_CEE_CPOBJ:
GSHAREDVT_FAILURE (il_op);
Expand Down
5 changes: 5 additions & 0 deletions src/mono/mono/mini/mini-ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,11 @@ MINI_OP(OP_FGETHIGH32, "float_gethigh32", IREG, FREG, NONE)

MINI_OP(OP_JUMP_TABLE, "jump_table", IREG, NONE, NONE)

/* Same as OP_IMUL_OVF_UN, but throws an OutOfMemoryException */
/* Emulated */
MINI_OP(OP_IMUL_OVF_UN_OOM, "int_mul_ovf_un_oom", IREG, IREG, IREG)
MINI_OP(OP_LMUL_OVF_UN_OOM, "long_mul_ovf_un_oom", LREG, LREG, LREG)

/* aot compiler */
MINI_OP(OP_AOTCONST, "aotconst", IREG, NONE, NONE)
MINI_OP(OP_PATCH_INFO, "patch_info", NONE, NONE, NONE)
Expand Down
2 changes: 2 additions & 0 deletions src/mono/mono/mini/mini-runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -4729,6 +4729,7 @@ register_icalls (void)
#if !defined(MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS) || defined(MONO_ARCH_EMULATE_LONG_MUL_OVF_OPTS)
register_opcode_emulation (OP_LMUL_OVF_UN, __emul_lmul_ovf_un, mono_icall_sig_long_long_long, mono_llmult_ovf_un, FALSE);
register_opcode_emulation (OP_LMUL_OVF, __emul_lmul_ovf, mono_icall_sig_long_long_long, mono_llmult_ovf, FALSE);
register_opcode_emulation (OP_LMUL_OVF_UN_OOM, __emul_lmul_ovf_un_oom, mono_icall_sig_long_long_long, mono_llmult_ovf_un_oom, FALSE);
#endif

#ifndef MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS
Expand All @@ -4751,6 +4752,7 @@ register_icalls (void)
#if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_MUL_OVF)
register_opcode_emulation (OP_IMUL_OVF, __emul_op_imul_ovf, mono_icall_sig_int32_int32_int32, mono_imul_ovf, FALSE);
register_opcode_emulation (OP_IMUL_OVF_UN, __emul_op_imul_ovf_un, mono_icall_sig_int32_int32_int32, mono_imul_ovf_un, FALSE);
register_opcode_emulation (OP_IMUL_OVF_UN_OOM, __emul_op_imul_ovf_un_oom, mono_icall_sig_int32_int32_int32, mono_imul_ovf_un_oom, FALSE);
#endif

#if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_SOFT_FLOAT_FALLBACK)
Expand Down
4 changes: 2 additions & 2 deletions src/mono/mono/mini/mini-x86.c
Original file line number Diff line number Diff line change
Expand Up @@ -2992,7 +2992,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
break;
case OP_IMUL_OVF:
x86_imul_reg_reg (code, ins->sreg1, ins->sreg2);
EMIT_COND_SYSTEM_EXCEPTION (X86_CC_O, FALSE, "OverflowException");
EMIT_COND_SYSTEM_EXCEPTION (X86_CC_O, FALSE, ins->inst_exc_name);
break;
case OP_IMUL_OVF_UN: {
/* the mul operation and the exception check should most likely be split */
Expand Down Expand Up @@ -3028,7 +3028,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
x86_pop_reg (code, X86_EDX);
if (saved_eax)
x86_pop_reg (code, X86_EAX);
EMIT_COND_SYSTEM_EXCEPTION (X86_CC_O, FALSE, "OverflowException");
EMIT_COND_SYSTEM_EXCEPTION (X86_CC_O, FALSE, ins->inst_exc_name);
break;
}
case OP_ICONST:
Expand Down

0 comments on commit edbe39f

Please sign in to comment.