From 53e841b4e09f2c715fe459a1e4a84e4de5c161fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Fri, 25 Aug 2017 10:15:25 +0200 Subject: Add annotations for likely/unlikely In a correct Erlang programs, we can expect that: * A GC test instruction (such as test_heap) is more likely not to do the GC. * A BIF is more likely to succeed than to fail. * A BIF is more likely to fail in a guard than in a body. * An apply or fun call is likely to succeed. Annotate conditions accordingly. --- erts/emulator/beam/bif_instrs.tab | 20 ++++++++++---------- erts/emulator/beam/instrs.tab | 24 ++++++++++++------------ erts/emulator/beam/macros.tab | 16 +++++++++++----- 3 files changed, 33 insertions(+), 27 deletions(-) (limited to 'erts/emulator/beam') diff --git a/erts/emulator/beam/bif_instrs.tab b/erts/emulator/beam/bif_instrs.tab index 5aa0523e06..3c95113907 100644 --- a/erts/emulator/beam/bif_instrs.tab +++ b/erts/emulator/beam/bif_instrs.tab @@ -45,7 +45,7 @@ CALL_GUARD_BIF(BF, TmpReg, Dst) { ERTS_HOLE_CHECK(c_p); FCALLS = c_p->fcalls; ERTS_DBG_CHK_REDS(c_p, FCALLS); - if (is_value(result)) { + if (ERTS_LIKELY(is_value(result))) { $Dst = result; $NEXT0(); } @@ -145,12 +145,12 @@ i_gc_bif1(Fail, Bif, Src, Live, Dst) { ERTS_HOLE_CHECK(c_p); FCALLS = c_p->fcalls; ERTS_DBG_CHK_REDS(c_p, FCALLS); - if (is_value(result)) { + if (ERTS_LIKELY(is_value(result))) { $REFRESH_GEN_DEST(); $Dst = result; $NEXT0(); } - if ($Fail != 0) { /* Handle error in guard. */ + if (ERTS_LIKELY($Fail != 0)) { /* Handle error in guard. */ $NEXT($Fail); } @@ -195,13 +195,13 @@ i_gc_bif2(Fail, Bif, Live, Src1, Src2, Dst) { ERTS_HOLE_CHECK(c_p); FCALLS = c_p->fcalls; ERTS_DBG_CHK_REDS(c_p, FCALLS); - if (is_value(result)) { + if (ERTS_LIKELY(is_value(result))) { $REFRESH_GEN_DEST(); $Dst = result; $NEXT0(); } - if ($Fail != 0) { /* Handle error in guard. */ + if (ERTS_LIKELY($Fail != 0)) { /* Handle error in guard. */ $NEXT($Fail); } @@ -249,14 +249,14 @@ i_gc_bif3(Fail, Bif, Live, Src2, Src3, Dst) { ERTS_HOLE_CHECK(c_p); FCALLS = c_p->fcalls; ERTS_DBG_CHK_REDS(c_p, FCALLS); - if (is_value(result)) { + if (ERTS_LIKELY(is_value(result))) { $REFRESH_GEN_DEST(); $Dst = result; $NEXT0(); } /* Handle error in guard. */ - if ($Fail != 0) { + if (ERTS_LIKELY($Fail != 0)) { $NEXT($Fail); } @@ -325,7 +325,7 @@ call_bif(Exp) { ERTS_MSACC_UPDATE_CACHE_X(); } ERTS_MSACC_SET_STATE_CACHED_M_X(ERTS_MSACC_STATE_EMULATOR); - if (is_value(result)) { + if (ERTS_LIKELY(is_value(result))) { r(0) = result; CHECK_TERM(r(0)); $NEXT0(); @@ -370,7 +370,7 @@ send() { PROCESS_MAIN_CHK_LOCKS(c_p); HTOP = HEAP_TOP(c_p); FCALLS = c_p->fcalls; - if (is_value(result)) { + if (ERTS_LIKELY(is_value(result))) { r(0) = result; CHECK_TERM(r(0)); } else if (c_p->freason == TRAP) { @@ -520,7 +520,7 @@ nif_bif.epilogue() { SWAPIN; /* There might have been a garbage collection. */ FCALLS = c_p->fcalls; ERTS_DBG_CHK_REDS(c_p, FCALLS); - if (is_value(nif_bif_result)) { + if (ERTS_LIKELY(is_value(nif_bif_result))) { r(0) = nif_bif_result; CHECK_TERM(r(0)); SET_I(c_p->cp); diff --git a/erts/emulator/beam/instrs.tab b/erts/emulator/beam/instrs.tab index 1af01e53bd..58432cbbb4 100644 --- a/erts/emulator/beam/instrs.tab +++ b/erts/emulator/beam/instrs.tab @@ -171,7 +171,7 @@ HANDLE_APPLY_ERROR() { i_apply() { BeamInstr *next; $APPLY(NULL, 0); - if (next != NULL) { + if (ERTS_LIKELY(next != NULL)) { $i_call(next); } $HANDLE_APPLY_ERROR(); @@ -180,7 +180,7 @@ i_apply() { i_apply_last(Deallocate) { BeamInstr *next; $APPLY(I, $Deallocate); - if (next != NULL) { + if (ERTS_LIKELY(next != NULL)) { $i_call_last(next, $Deallocate); } $HANDLE_APPLY_ERROR(); @@ -189,7 +189,7 @@ i_apply_last(Deallocate) { i_apply_only() { BeamInstr *next; $APPLY(I, 0); - if (next != NULL) { + if (ERTS_LIKELY(next != NULL)) { $i_call_only(next); } $HANDLE_APPLY_ERROR(); @@ -205,7 +205,7 @@ FIXED_APPLY(Arity, I, Deallocate) { apply(Arity) { BeamInstr *next; $FIXED_APPLY($Arity, NULL, 0); - if (next != NULL) { + if (ERTS_LIKELY(next != NULL)) { $i_call(next); } $HANDLE_APPLY_ERROR(); @@ -214,7 +214,7 @@ apply(Arity) { apply_last(Arity, Deallocate) { BeamInstr *next; $FIXED_APPLY($Arity, I, $Deallocate); - if (next != NULL) { + if (ERTS_LIKELY(next != NULL)) { $i_call_last(next, $Deallocate); } $HANDLE_APPLY_ERROR(); @@ -238,7 +238,7 @@ DISPATCH_FUN(I) { i_apply_fun() { BeamInstr *next; $APPLY_FUN(); - if (next != NULL) { + if (ERTS_LIKELY(next != NULL)) { SET_CP(c_p, $NEXT_INSTRUCTION); $DISPATCH_FUN(next); } @@ -248,7 +248,7 @@ i_apply_fun() { i_apply_fun_last(Deallocate) { BeamInstr *next; $APPLY_FUN(); - if (next != NULL) { + if (ERTS_LIKELY(next != NULL)) { $deallocate($Deallocate); $DISPATCH_FUN(next); } @@ -258,7 +258,7 @@ i_apply_fun_last(Deallocate) { i_apply_fun_only() { BeamInstr *next; $APPLY_FUN(); - if (next != NULL) { + if (ERTS_LIKELY(next != NULL)) { $DISPATCH_FUN(next); } $HANDLE_APPLY_FUN_ERROR(); @@ -274,7 +274,7 @@ CALL_FUN(Fun) { i_call_fun(Fun) { BeamInstr *next; $CALL_FUN($Fun); - if (next != NULL) { + if (ERTS_LIKELY(next != NULL)) { SET_CP(c_p, $NEXT_INSTRUCTION); $DISPATCH_FUN(next); } @@ -284,7 +284,7 @@ i_call_fun(Fun) { i_call_fun_last(Fun, Deallocate) { BeamInstr *next; $CALL_FUN($Fun); - if (next != NULL) { + if (ERTS_LIKELY(next != NULL)) { $deallocate($Deallocate); $DISPATCH_FUN(next); } @@ -378,7 +378,7 @@ element_group.fetch(Src) { element_group.execute(Fail, Index, Dst) { element_index = $Index; - if (is_small(element_index) && is_tuple(element_tuple)) { + if (ERTS_LIKELY(is_small(element_index) && is_tuple(element_tuple))) { Eterm* tp = tuple_val(element_tuple); if ((signed_val(element_index) >= 1) && @@ -402,7 +402,7 @@ fast_element_group.fetch(Src) { } fast_element_group.execute(Fail, Index, Dst) { - if (is_tuple(fast_element_tuple)) { + if (ERTS_LIKELY(is_tuple(fast_element_tuple))) { Eterm* tp = tuple_val(fast_element_tuple); Eterm pos = $Index; /* Untagged integer >= 1 */ if (pos <= arityval(*tp)) { diff --git a/erts/emulator/beam/macros.tab b/erts/emulator/beam/macros.tab index 41dc761e90..bac96be7d3 100644 --- a/erts/emulator/beam/macros.tab +++ b/erts/emulator/beam/macros.tab @@ -42,7 +42,7 @@ JUMP(Fail) { GC_TEST(Ns, Nh, Live) { Uint need = $Nh + $Ns; - if (E - HTOP < need) { + if (ERTS_UNLIKELY(E - HTOP < need)) { SWAPOUT; PROCESS_MAIN_CHK_LOCKS(c_p); FCALLS -= erts_garbage_collect_nobump(c_p, need, reg, $Live, FCALLS); @@ -55,7 +55,7 @@ GC_TEST(Ns, Nh, Live) { GC_TEST_PRESERVE(NeedHeap, Live, PreserveTerm) { Uint need = $NeedHeap; - if (E - HTOP < need) { + if (ERTS_UNLIKELY(E - HTOP < need)) { SWAPOUT; reg[$Live] = $PreserveTerm; PROCESS_MAIN_CHK_LOCKS(c_p); @@ -99,7 +99,13 @@ FAIL_BODY() { FAIL_HEAD_OR_BODY(Fail) { //| -no_prefetch - if ($Fail) { + + /* + * In a correctly working program, we expect failures in + * guards to be more likely than failures in bodies. + */ + + if (ERTS_LIKELY($Fail)) { $FAIL($Fail); } goto find_func_info; @@ -122,7 +128,7 @@ SYSTEM_LIMIT(Fail) { BIF_ERROR_ARITY_1(Fail, BIF, Op1) { //| -no_prefetch - if ($Fail) { + if (ERTS_LIKELY($Fail)) { $FAIL($Fail); } reg[0] = $Op1; @@ -133,7 +139,7 @@ BIF_ERROR_ARITY_1(Fail, BIF, Op1) { BIF_ERROR_ARITY_2(Fail, BIF, Op1, Op2) { //| -no_prefetch - if ($Fail) { + if (ERTS_LIKELY($Fail)) { $FAIL($Fail); } reg[0] = $Op1; -- cgit v1.2.3