diff options
author | Sverker Eriksson <[email protected]> | 2014-02-25 15:27:59 +0100 |
---|---|---|
committer | Sverker Eriksson <[email protected]> | 2014-02-25 15:27:59 +0100 |
commit | b9440a0529bea5ccc3f4341db29ddda6f4b7c536 (patch) | |
tree | fbd7e7c946eb9621fe1f923d04f857b921bd8378 /erts/emulator/beam | |
parent | 98776a40609d1fa80292d2959708a8697f8cb756 (diff) | |
parent | eb53a3f0b7a7d6c4d0a877fe71bc0b0ca11d1597 (diff) | |
download | otp-b9440a0529bea5ccc3f4341db29ddda6f4b7c536.tar.gz otp-b9440a0529bea5ccc3f4341db29ddda6f4b7c536.tar.bz2 otp-b9440a0529bea5ccc3f4341db29ddda6f4b7c536.zip |
Merge branch 'sverk/hipe-disable-gc-bug'
* sverk/hipe-disable-gc-bug:
erts: Fix heap overwrite by hipe "trap frames" when GC is disabled
ASSERT that GC is not tried with "need" when GC is disabled
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r-- | erts/emulator/beam/erl_gc.c | 4 | ||||
-rw-r--r-- | erts/emulator/beam/external.c | 65 |
2 files changed, 67 insertions, 2 deletions
diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c index 2022f70cbb..aa15d2cc57 100644 --- a/erts/emulator/beam/erl_gc.c +++ b/erts/emulator/beam/erl_gc.c @@ -406,8 +406,10 @@ erts_garbage_collect(Process* p, int need, Eterm* objv, int nobj) DTRACE_CHARBUF(pidbuf, DTRACE_TERM_BUF_SIZE); #endif - if (p->flags & F_DISABLE_GC) + if (p->flags & F_DISABLE_GC) { + ASSERT(need == 0); return 1; + } esdp = erts_get_scheduler_data(); diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c index b8e6b3b072..9671cde228 100644 --- a/erts/emulator/beam/external.c +++ b/erts/emulator/beam/external.c @@ -1068,7 +1068,7 @@ static BIF_RETTYPE term_to_binary_trap_1(BIF_ALIST_1) BIF_RET(res); } } - + BIF_RETTYPE term_to_binary_1(BIF_ALIST_1) { Eterm res = erts_term_to_binary_int(BIF_P, BIF_ARG_1, 0, TERM_TO_BINARY_DFLAGS, NULL); @@ -4459,3 +4459,66 @@ error: #undef SKIP2 #undef CHKSIZE } + + +#ifdef HIPE +BIF_RETTYPE hipe_wrapper_term_to_binary_1(BIF_ALIST_1); +BIF_RETTYPE hipe_wrapper_term_to_binary_2(BIF_ALIST_2); +BIF_RETTYPE hipe_wrapper_erts_internal_binary_to_term_1(BIF_ALIST_1); +BIF_RETTYPE hipe_wrapper_erts_internal_binary_to_term_2(BIF_ALIST_2); + +/* Hipe wrappers used by native code for BIFs that disable GC while trapping. + * + * Problem: + * When native code calls a BIF that traps, hipe_mode_switch will push a + * "trap frame" on the Erlang stack in order to find its way back from beam_emu + * back to native caller when finally done. If GC is disabled and stack/heap + * is full there is no place to push the "trap frame". + * + * Solution: + * We reserve space on stack for the "trap frame" here before the BIF is called. + * If the BIF does not trap, the space is reclaimed here before returning. + * If the BIF traps, hipe_push_beam_trap_frame() will detect that a "trap frame" + * already is reserved and use it. + */ +BIF_RETTYPE hipe_wrapper_term_to_binary_1(BIF_ALIST_1) +{ + Eterm res; + hipe_reserve_beam_trap_frame(BIF_P, BIF__ARGS, 1); + res = term_to_binary_1(BIF_P, BIF__ARGS); + if (is_value(res) || BIF_P->freason != TRAP) { + hipe_unreserve_beam_trap_frame(BIF_P); + } + return res; +} +BIF_RETTYPE hipe_wrapper_term_to_binary_2(BIF_ALIST_2) +{ + Eterm res; + hipe_reserve_beam_trap_frame(BIF_P, BIF__ARGS, 2); + res = term_to_binary_2(BIF_P, BIF__ARGS); + if (is_value(res) || BIF_P->freason != TRAP) { + hipe_unreserve_beam_trap_frame(BIF_P); + } + return res; +} +BIF_RETTYPE hipe_wrapper_erts_internal_binary_to_term_1(BIF_ALIST_1) +{ + Eterm res; + hipe_reserve_beam_trap_frame(BIF_P, BIF__ARGS, 1); + res = erts_internal_binary_to_term_1(BIF_P, BIF__ARGS); + if (is_value(res) || BIF_P->freason != TRAP) { + hipe_unreserve_beam_trap_frame(BIF_P); + } + return res; +} +BIF_RETTYPE hipe_wrapper_erts_internal_binary_to_term_2(BIF_ALIST_2) +{ + Eterm res; + hipe_reserve_beam_trap_frame(BIF_P, BIF__ARGS, 2); + res = erts_internal_binary_to_term_2(BIF_P, BIF__ARGS); + if (is_value(res) || BIF_P->freason != TRAP) { + hipe_unreserve_beam_trap_frame(BIF_P); + } + return res; +} +#endif /*HIPE*/ |