aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2017-08-25 10:15:25 +0200
committerBjörn Gustavsson <[email protected]>2017-08-31 15:45:31 +0200
commit53e841b4e09f2c715fe459a1e4a84e4de5c161fa (patch)
tree60d10d6ee3bbae7ab1bdb7ff4ea956a97f0f6bfc
parent3280aa8f8398b2b6a1bb78aedc27fc7e73653288 (diff)
downloadotp-53e841b4e09f2c715fe459a1e4a84e4de5c161fa.tar.gz
otp-53e841b4e09f2c715fe459a1e4a84e4de5c161fa.tar.bz2
otp-53e841b4e09f2c715fe459a1e4a84e4de5c161fa.zip
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.
-rw-r--r--erts/emulator/beam/bif_instrs.tab20
-rw-r--r--erts/emulator/beam/instrs.tab24
-rw-r--r--erts/emulator/beam/macros.tab16
3 files changed, 33 insertions, 27 deletions
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;