aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator')
-rw-r--r--erts/emulator/beam/beam_emu.c29
-rw-r--r--erts/emulator/beam/erl_process.c4
-rw-r--r--erts/emulator/beam/erl_process.h2
-rw-r--r--erts/emulator/hipe/hipe_amd64_bifs.m42
-rw-r--r--erts/emulator/hipe/hipe_amd64_primops.h2
-rw-r--r--erts/emulator/hipe/hipe_bif0.c20
-rw-r--r--erts/emulator/hipe/hipe_bif0.tab2
-rw-r--r--erts/emulator/hipe/hipe_bif_list.m44
-rw-r--r--erts/emulator/hipe/hipe_mkliterals.c16
-rw-r--r--erts/emulator/hipe/hipe_native_bif.c2
-rw-r--r--erts/emulator/hipe/hipe_native_bif.h5
-rw-r--r--erts/emulator/hipe/hipe_primops.h4
-rw-r--r--erts/emulator/hipe/hipe_process.h3
-rw-r--r--erts/emulator/hipe/hipe_x86.h2
-rw-r--r--erts/emulator/hipe/hipe_x86_bifs.m42
-rw-r--r--erts/emulator/hipe/hipe_x86_primops.h3
-rw-r--r--erts/emulator/test/float_SUITE.erl27
17 files changed, 110 insertions, 19 deletions
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c
index 9c5450bd48..028a532b4c 100644
--- a/erts/emulator/beam/beam_emu.c
+++ b/erts/emulator/beam/beam_emu.c
@@ -4747,7 +4747,12 @@ void process_main(void)
OpCase(fclearerror):
OpCase(i_fcheckerror):
erl_exit(1, "fclearerror/i_fcheckerror without fpe signals (beam_emu)");
+# define ERTS_NO_FPE_CHECK_INIT ERTS_FP_CHECK_INIT
+# define ERTS_NO_FPE_ERROR ERTS_FP_ERROR
#else
+# define ERTS_NO_FPE_CHECK_INIT(p)
+# define ERTS_NO_FPE_ERROR(p, a, b)
+
OpCase(fclearerror): {
BeamInstr *next;
@@ -4763,10 +4768,6 @@ void process_main(void)
ERTS_FP_ERROR(c_p, freg[0].fd, goto fbadarith);
NextPF(0, next);
}
-# undef ERTS_FP_CHECK_INIT
-# undef ERTS_FP_ERROR
-# define ERTS_FP_CHECK_INIT(p)
-# define ERTS_FP_ERROR(p, a, b)
#endif
@@ -4774,45 +4775,45 @@ void process_main(void)
BeamInstr *next;
PreFetch(3, next);
- ERTS_FP_CHECK_INIT(c_p);
+ ERTS_NO_FPE_CHECK_INIT(c_p);
fb(Arg(2)) = fb(Arg(0)) + fb(Arg(1));
- ERTS_FP_ERROR(c_p, fb(Arg(2)), goto fbadarith);
+ ERTS_NO_FPE_ERROR(c_p, fb(Arg(2)), goto fbadarith);
NextPF(3, next);
}
OpCase(i_fsub_lll): {
BeamInstr *next;
PreFetch(3, next);
- ERTS_FP_CHECK_INIT(c_p);
+ ERTS_NO_FPE_CHECK_INIT(c_p);
fb(Arg(2)) = fb(Arg(0)) - fb(Arg(1));
- ERTS_FP_ERROR(c_p, fb(Arg(2)), goto fbadarith);
+ ERTS_NO_FPE_ERROR(c_p, fb(Arg(2)), goto fbadarith);
NextPF(3, next);
}
OpCase(i_fmul_lll): {
BeamInstr *next;
PreFetch(3, next);
- ERTS_FP_CHECK_INIT(c_p);
+ ERTS_NO_FPE_CHECK_INIT(c_p);
fb(Arg(2)) = fb(Arg(0)) * fb(Arg(1));
- ERTS_FP_ERROR(c_p, fb(Arg(2)), goto fbadarith);
+ ERTS_NO_FPE_ERROR(c_p, fb(Arg(2)), goto fbadarith);
NextPF(3, next);
}
OpCase(i_fdiv_lll): {
BeamInstr *next;
PreFetch(3, next);
- ERTS_FP_CHECK_INIT(c_p);
+ ERTS_NO_FPE_CHECK_INIT(c_p);
fb(Arg(2)) = fb(Arg(0)) / fb(Arg(1));
- ERTS_FP_ERROR(c_p, fb(Arg(2)), goto fbadarith);
+ ERTS_NO_FPE_ERROR(c_p, fb(Arg(2)), goto fbadarith);
NextPF(3, next);
}
OpCase(i_fnegate_ll): {
BeamInstr *next;
PreFetch(2, next);
- ERTS_FP_CHECK_INIT(c_p);
+ ERTS_NO_FPE_CHECK_INIT(c_p);
fb(Arg(1)) = -fb(Arg(0));
- ERTS_FP_ERROR(c_p, fb(Arg(1)), goto fbadarith);
+ ERTS_NO_FPE_ERROR(c_p, fb(Arg(1)), goto fbadarith);
NextPF(2, next);
fbadarith:
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index a1f5069b2d..84c0ded016 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -7140,7 +7140,7 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
p->pending_exit.bp = NULL;
#endif
-#if !defined(NO_FPE_SIGNALS)
+#if !defined(NO_FPE_SIGNALS) || defined(HIPE)
p->fp_exception = 0;
#endif
@@ -7314,7 +7314,7 @@ void erts_init_empty_process(Process *p)
p->run_queue = ERTS_RUNQ_IX(0);
#endif
-#if !defined(NO_FPE_SIGNALS)
+#if !defined(NO_FPE_SIGNALS) || defined(HIPE)
p->fp_exception = 0;
#endif
diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h
index f0c86a0851..69ff423133 100644
--- a/erts/emulator/beam/erl_process.h
+++ b/erts/emulator/beam/erl_process.h
@@ -618,7 +618,7 @@ struct process {
Uint min_heap_size; /* Minimum size of heap (in words). */
Uint min_vheap_size; /* Minimum size of virtual heap (in words). */
-#if !defined(NO_FPE_SIGNALS)
+#if !defined(NO_FPE_SIGNALS) || defined(HIPE)
volatile unsigned long fp_exception;
#endif
diff --git a/erts/emulator/hipe/hipe_amd64_bifs.m4 b/erts/emulator/hipe/hipe_amd64_bifs.m4
index 97a8267647..ec25c0b9b7 100644
--- a/erts/emulator/hipe/hipe_amd64_bifs.m4
+++ b/erts/emulator/hipe/hipe_amd64_bifs.m4
@@ -549,7 +549,9 @@ ASYM($1):
/*
* AMD64-specific primops.
*/
+#ifndef NO_FPE_SIGNALS
noproc_primop_interface_0(nbif_handle_fp_exception, erts_restore_fpu)
+#endif /* NO_FPE_SIGNALS */
/*
* Implement gc_bif_interface_0 as nofail_primop_interface_0.
diff --git a/erts/emulator/hipe/hipe_amd64_primops.h b/erts/emulator/hipe/hipe_amd64_primops.h
index e3c7111997..55cb0eadb8 100644
--- a/erts/emulator/hipe/hipe_amd64_primops.h
+++ b/erts/emulator/hipe/hipe_amd64_primops.h
@@ -19,5 +19,7 @@
PRIMOP_LIST(am_inc_stack_0, &nbif_inc_stack_0)
+#ifndef NO_FPE_SIGNALS
PRIMOP_LIST(am_handle_fp_exception, &nbif_handle_fp_exception)
+#endif
PRIMOP_LIST(am_sse2_fnegate_mask, &sse2_fnegate_mask)
diff --git a/erts/emulator/hipe/hipe_bif0.c b/erts/emulator/hipe/hipe_bif0.c
index e7fb850530..cec22b3836 100644
--- a/erts/emulator/hipe/hipe_bif0.c
+++ b/erts/emulator/hipe/hipe_bif0.c
@@ -985,6 +985,26 @@ BIF_RETTYPE hipe_conv_big_to_float(BIF_ALIST_1)
BIF_RET(res);
}
+#ifdef NO_FPE_SIGNALS
+
+/*
+ This is the current solution to make hipe run without FPE.
+ The native code is the same except that a call to this primop
+ is made after _every_ float operation to check the result.
+ The native fcheckerror still done later will detect if an
+ "emulated" FPE has occured.
+ We use p->hipe.float_result to avoid passing a 'double' argument,
+ which has its own calling convention (on amd64 at least).
+ Simple and slow...
+*/
+void hipe_emulate_fpe(Process* p)
+{
+ if (!finite(p->hipe.float_result)) {
+ p->fp_exception = 1;
+ }
+}
+#endif
+
#if 0 /* XXX: unused */
/*
* At least parts of this should be inlined in native code.
diff --git a/erts/emulator/hipe/hipe_bif0.tab b/erts/emulator/hipe/hipe_bif0.tab
index b6c6bede23..ce641365e9 100644
--- a/erts/emulator/hipe/hipe_bif0.tab
+++ b/erts/emulator/hipe/hipe_bif0.tab
@@ -140,3 +140,5 @@ atom bs_put_utf16le
atom bs_get_utf16
atom bs_validate_unicode
atom bs_validate_unicode_retract
+atom emulate_fpe
+
diff --git a/erts/emulator/hipe/hipe_bif_list.m4 b/erts/emulator/hipe/hipe_bif_list.m4
index 48c7c1bc9b..942fa0c5cb 100644
--- a/erts/emulator/hipe/hipe_bif_list.m4
+++ b/erts/emulator/hipe/hipe_bif_list.m4
@@ -245,6 +245,10 @@ noproc_primop_interface_5(nbif_bs_put_big_integer, hipe_bs_put_big_integer)
gc_bif_interface_0(nbif_check_get_msg, hipe_check_get_msg)
+#ifdef NO_FPE_SIGNALS
+nocons_nofail_primop_interface_0(nbif_emulate_fpe, hipe_emulate_fpe)
+#endif
+
/*
* SMP-specific stuff
*/
diff --git a/erts/emulator/hipe/hipe_mkliterals.c b/erts/emulator/hipe/hipe_mkliterals.c
index 61e15f1d58..d07d14028c 100644
--- a/erts/emulator/hipe/hipe_mkliterals.c
+++ b/erts/emulator/hipe/hipe_mkliterals.c
@@ -293,6 +293,11 @@ static const struct literal {
{ "P_NRA", offsetof(struct process, hipe.nra) },
#endif
{ "P_NARITY", offsetof(struct process, hipe.narity) },
+ { "P_FLOAT_RESULT",
+# ifdef NO_FPE_SIGNALS
+ offsetof(struct process, hipe.float_result)
+# endif
+ },
# if defined(ERTS_ENABLE_LOCK_CHECK) && defined(ERTS_SMP)
{ "P_BIF_CALLEE", offsetof(struct process, hipe.bif_callee) },
# endif
@@ -491,7 +496,7 @@ static const struct rts_param {
#endif
},
{ 14, "P_FP_EXCEPTION",
-#if !defined(NO_FPE_SIGNALS)
+#if !defined(NO_FPE_SIGNALS) || defined(HIPE)
1, offsetof(struct process, fp_exception)
#endif
},
@@ -504,6 +509,15 @@ static const struct rts_param {
0
#endif
},
+ /* This flag is always defined, but its value is configuration-dependent. */
+ { 16, "ERTS_NO_FPE_SIGNALS",
+ 1,
+#if defined(NO_FPE_SIGNALS)
+ 1
+#else
+ 0
+#endif
+ },
/* This parameter is always defined, but its value depends on ERTS_SMP. */
{ 19, "MSG_MESSAGE",
1, offsetof(struct erl_mesg, m[0])
diff --git a/erts/emulator/hipe/hipe_native_bif.c b/erts/emulator/hipe/hipe_native_bif.c
index 77dee6f9e9..3be821f8f7 100644
--- a/erts/emulator/hipe/hipe_native_bif.c
+++ b/erts/emulator/hipe/hipe_native_bif.c
@@ -189,6 +189,8 @@ void hipe_fclearerror_error(Process *p)
{
#if !defined(NO_FPE_SIGNALS)
erts_fp_check_init_error(&p->fp_exception);
+#else
+ erl_exit(ERTS_ABORT_EXIT, "Emulated FPE not cleared by HiPE");
#endif
}
diff --git a/erts/emulator/hipe/hipe_native_bif.h b/erts/emulator/hipe/hipe_native_bif.h
index 8c9dec180e..9e3a156fbc 100644
--- a/erts/emulator/hipe/hipe_native_bif.h
+++ b/erts/emulator/hipe/hipe_native_bif.h
@@ -93,6 +93,11 @@ BIF_RETTYPE hipe_bs_validate_unicode(BIF_ALIST_1);
struct erl_bin_match_buffer;
int hipe_bs_validate_unicode_retract(struct erl_bin_match_buffer*, Eterm);
+#ifdef NO_FPE_SIGNALS
+AEXTERN(void,nbif_emulate_fpe,(Process*));
+void hipe_emulate_fpe(Process*);
+#endif
+
/*
* Stuff that is different in SMP and non-SMP.
*/
diff --git a/erts/emulator/hipe/hipe_primops.h b/erts/emulator/hipe/hipe_primops.h
index 94113ffcd8..38509c105b 100644
--- a/erts/emulator/hipe/hipe_primops.h
+++ b/erts/emulator/hipe/hipe_primops.h
@@ -77,6 +77,10 @@ PRIMOP_LIST(am_nonclosure_address, &nbif_nonclosure_address)
PRIMOP_LIST(am_conv_big_to_float, &nbif_conv_big_to_float)
PRIMOP_LIST(am_fclearerror_error, &nbif_fclearerror_error)
+#ifdef NO_FPE_SIGNALS
+PRIMOP_LIST(am_emulate_fpe, &nbif_emulate_fpe)
+#endif
+
#if defined(__sparc__)
#include "hipe_sparc_primops.h"
#endif
diff --git a/erts/emulator/hipe/hipe_process.h b/erts/emulator/hipe/hipe_process.h
index 43f47d1a28..4ee99d78a2 100644
--- a/erts/emulator/hipe/hipe_process.h
+++ b/erts/emulator/hipe/hipe_process.h
@@ -42,6 +42,9 @@ struct hipe_process_state {
void (*nra)(void); /* Native code return address. */
#endif
unsigned int narity; /* Arity of BIF call, for stack walks. */
+#ifdef NO_FPE_SIGNALS
+ double float_result; /* to be checked for inf/NaN by hipe_emulate_fpe */
+#endif
#if defined(ERTS_ENABLE_LOCK_CHECK) && defined(ERTS_SMP)
void (*bif_callee)(void); /* When calling BIF's via debug wrapper */
#endif
diff --git a/erts/emulator/hipe/hipe_x86.h b/erts/emulator/hipe/hipe_x86.h
index f0f3c158af..97f09e38cd 100644
--- a/erts/emulator/hipe/hipe_x86.h
+++ b/erts/emulator/hipe/hipe_x86.h
@@ -49,7 +49,9 @@ static __inline__ int hipe_word32_address_ok(void *address)
#define hipe_arch_name am_x86
extern void nbif_inc_stack_0(void);
+#ifndef NO_FPE_SIGNALS
extern void nbif_handle_fp_exception(void);
+#endif
/* for hipe_bifs_enter_code_2 */
extern void *hipe_alloc_code(Uint nrbytes, Eterm callees, Eterm *trampolines, Process *p);
diff --git a/erts/emulator/hipe/hipe_x86_bifs.m4 b/erts/emulator/hipe/hipe_x86_bifs.m4
index 2ea69bde3c..3cb7d67be0 100644
--- a/erts/emulator/hipe/hipe_x86_bifs.m4
+++ b/erts/emulator/hipe/hipe_x86_bifs.m4
@@ -621,7 +621,9 @@ ASYM($1):
/*
* x86-specific primops.
*/
+#ifndef NO_FPE_SIGNALS
noproc_primop_interface_0(nbif_handle_fp_exception, erts_restore_fpu)
+#endif /* NO_FPE_SIGNALS */
/*
* Implement gc_bif_interface_0 as nofail_primop_interface_0.
diff --git a/erts/emulator/hipe/hipe_x86_primops.h b/erts/emulator/hipe/hipe_x86_primops.h
index 96d2336bc5..111b1fa8bd 100644
--- a/erts/emulator/hipe/hipe_x86_primops.h
+++ b/erts/emulator/hipe/hipe_x86_primops.h
@@ -19,4 +19,7 @@
PRIMOP_LIST(am_inc_stack_0, &nbif_inc_stack_0)
+#ifndef NO_FPE_SIGNALS
PRIMOP_LIST(am_handle_fp_exception, &nbif_handle_fp_exception)
+#endif
+
diff --git a/erts/emulator/test/float_SUITE.erl b/erts/emulator/test/float_SUITE.erl
index 46466427c5..8e6923ce9f 100644
--- a/erts/emulator/test/float_SUITE.erl
+++ b/erts/emulator/test/float_SUITE.erl
@@ -27,6 +27,7 @@
fpe/1,fp_drv/1,fp_drv_thread/1,denormalized/1,match/1,
bad_float_unpack/1,cmp_zero/1, cmp_integer/1, cmp_bignum/1]).
-export([otp_7178/1]).
+-export([hidden_inf/1]).
init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
@@ -41,7 +42,9 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[fpe, fp_drv, fp_drv_thread, otp_7178, denormalized,
- match, bad_float_unpack, {group, comparison}].
+ match, bad_float_unpack, {group, comparison}
+ ,hidden_inf
+ ].
groups() ->
[{comparison, [parallel], [cmp_zero, cmp_integer, cmp_bignum]}].
@@ -300,3 +303,25 @@ start_node(Config) when is_list(Config) ->
stop_node(Node) ->
?t:stop_node(Node).
+
+
+%% Test that operations that might hide infinite intermediate results
+%% do not supress the badarith.
+hidden_inf(Config) when is_list(Config) ->
+ ZeroP = 0.0,
+ ZeroN = id(ZeroP) * (-1),
+ [hidden_inf_1(A, B, Z, 9.23e307)
+ || A <- [1.0, -1.0, 3.1415, -0.00001000131, 3.57e257, ZeroP, ZeroN],
+ B <- [1.0, -1.0, 3.1415, -0.00001000131, 3.57e257, ZeroP, ZeroN],
+ Z <- [ZeroP, ZeroN]],
+ ok.
+
+hidden_inf_1(A, B, Zero, Huge) ->
+ {'EXIT',{badarith,_}} = (catch (B / (A / Zero))),
+ {'EXIT',{badarith,_}} = (catch (B * (A / Zero))),
+ {'EXIT',{badarith,_}} = (catch (B / (Huge * Huge))),
+ {'EXIT',{badarith,_}} = (catch (B * (Huge * Huge))),
+ {'EXIT',{badarith,_}} = (catch (B / (Huge + Huge))),
+ {'EXIT',{badarith,_}} = (catch (B * (Huge + Huge))),
+ {'EXIT',{badarith,_}} = (catch (B / (-Huge - Huge))),
+ {'EXIT',{badarith,_}} = (catch (B * (-Huge - Huge))).