aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2019-08-18 08:31:53 +0200
committerBjörn Gustavsson <[email protected]>2019-08-22 13:37:41 +0200
commit07a323813a47f92abf05bdf2255dc1354e82c55c (patch)
treef4880adf3724afab82c5973eea860a97b5cc2e96
parent8041849a8e55281b4d954e63e9415995607e1870 (diff)
downloadotp-07a323813a47f92abf05bdf2255dc1354e82c55c.tar.gz
otp-07a323813a47f92abf05bdf2255dc1354e82c55c.tar.bz2
otp-07a323813a47f92abf05bdf2255dc1354e82c55c.zip
Optimize the move_call instructions
The `move_call` instructions are combinations of a `move` instruction and a `call` instruction. As currently implemented, the `move` part of the instruction is executed in its entirety before the `call` part is even started. The reason is that the C compiler cannot see that it would be safe to read the target address of the call before writing to the move destination. Rewrite the instructions to explicitly read both the source for the move and the target address for the call before writing the destination of the move. Micro-benchmarks show a small but consistent speed-up after this change.
-rw-r--r--erts/emulator/beam/instrs.tab45
1 files changed, 30 insertions, 15 deletions
diff --git a/erts/emulator/beam/instrs.tab b/erts/emulator/beam/instrs.tab
index 807f4512d1..156de67716 100644
--- a/erts/emulator/beam/instrs.tab
+++ b/erts/emulator/beam/instrs.tab
@@ -165,9 +165,11 @@ i_call(CallDest) {
}
move_call(Src, CallDest) {
- x(0) = $Src;
+ Eterm call_dest = $CallDest;
+ Eterm src = $Src;
$SAVE_CONTINUATION_POINTER($NEXT_INSTRUCTION);
- $DISPATCH_REL($CallDest);
+ x(0) = src;
+ $DISPATCH_REL(call_dest);
}
i_call_last(CallDest, Deallocate) {
@@ -176,8 +178,11 @@ i_call_last(CallDest, Deallocate) {
}
move_call_last(Src, CallDest, Deallocate) {
- x(0) = $Src;
- $i_call_last($CallDest, $Deallocate);
+ Eterm call_dest = $CallDest;
+ Eterm src = $Src;
+ $deallocate($Deallocate);
+ x(0) = src;
+ $DISPATCH_REL(call_dest);
}
i_call_only(CallDest) {
@@ -185,8 +190,10 @@ i_call_only(CallDest) {
}
move_call_only(Src, CallDest) {
- x(0) = $Src;
- $i_call_only($CallDest);
+ Eterm call_dest = $CallDest;
+ Eterm src = $Src;
+ x(0) = src;
+ $DISPATCH_REL(call_dest);
}
DISPATCHX(Dest) {
@@ -202,18 +209,23 @@ i_call_ext(Dest) {
$DISPATCHX($Dest);
}
-i_move_call_ext(Src, Dest) {
- x(0) = $Src;
- $i_call_ext($Dest);
+i_move_call_ext(Src, CallDest) {
+ Eterm call_dest = $CallDest;
+ Eterm src = $Src;
+ $SAVE_CONTINUATION_POINTER($NEXT_INSTRUCTION);
+ x(0) = src;
+ $DISPATCHX(call_dest);
}
i_call_ext_only(Dest) {
$DISPATCHX($Dest);
}
-i_move_call_ext_only(Dest, Src) {
- x(0) = $Src;
- $i_call_ext_only($Dest);
+i_move_call_ext_only(CallDest, Src) {
+ Eterm call_dest = $CallDest;
+ Eterm src = $Src;
+ x(0) = src;
+ $DISPATCHX(call_dest);
}
i_call_ext_last(Dest, Deallocate) {
@@ -221,9 +233,12 @@ i_call_ext_last(Dest, Deallocate) {
$DISPATCHX($Dest);
}
-i_move_call_ext_last(Dest, StackOffset, Src) {
- x(0) = $Src;
- $i_call_ext_last($Dest, $StackOffset);
+i_move_call_ext_last(CallDest, Deallocate, Src) {
+ Eterm call_dest = $CallDest;
+ Eterm src = $Src;
+ $deallocate($Deallocate);
+ x(0) = src;
+ $DISPATCHX(call_dest);
}
APPLY(I, Deallocate, Next) {