diff options
author | Björn Gustavsson <[email protected]> | 2019-08-18 08:31:53 +0200 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2019-08-22 13:37:41 +0200 |
commit | 07a323813a47f92abf05bdf2255dc1354e82c55c (patch) | |
tree | f4880adf3724afab82c5973eea860a97b5cc2e96 | |
parent | 8041849a8e55281b4d954e63e9415995607e1870 (diff) | |
download | otp-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.tab | 45 |
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) { |