aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator
diff options
context:
space:
mode:
authorMichał Muskała <[email protected]>2018-12-13 16:26:11 +0100
committerMichał Muskała <[email protected]>2018-12-17 13:25:28 +0100
commit12f831fd482b5677aff5529374b55c73757f5246 (patch)
tree83ce66fa3c10a8ada16cea2b7db6c0045df18387 /erts/emulator
parent472b0669788e155f28851999b4e60bf8302ca2d5 (diff)
downloadotp-12f831fd482b5677aff5529374b55c73757f5246.tar.gz
otp-12f831fd482b5677aff5529374b55c73757f5246.tar.bz2
otp-12f831fd482b5677aff5529374b55c73757f5246.zip
Use microops for BIFs
This allows bif1/2/3 to share the main part of the code. The price is that we always need to copy all three temporary registers when error handling in bodies, but that should be infrequent. Additionally it makes it a bit harder to read the disasembly since now the arguments to BIFs are in the reverse order.
Diffstat (limited to 'erts/emulator')
-rw-r--r--erts/emulator/beam/bif_instrs.tab101
-rw-r--r--erts/emulator/beam/ops.tab32
2 files changed, 50 insertions, 83 deletions
diff --git a/erts/emulator/beam/bif_instrs.tab b/erts/emulator/beam/bif_instrs.tab
index 3abd062552..99abe662d5 100644
--- a/erts/emulator/beam/bif_instrs.tab
+++ b/erts/emulator/beam/bif_instrs.tab
@@ -58,103 +58,70 @@ CALL_GUARD_BIF(BF, TmpReg, Dst) {
}
}
-// Guard BIF in head. On failure, ignore the error and jump
-// to the code for the next clause. We don't support tracing
+// Guard BIF in head. On failure, ignore the error and jump
+// to the code for the next clause. We don't support tracing
// of guard BIFs.
-i_bif1(Fail, Bif, Src, Dst) {
+i_bif1 := i_bif.fetch0.call;
+i_bif2 := i_bif.fetch1.fetch0.call;
+i_bif3 := i_bif.fetch2.fetch1.fetch0.call;
+
+i_bif.head() {
ErtsBifFunc bf;
- Eterm tmp_reg[1];
+ Eterm tmp_reg[3];
+}
+i_bif.fetch0(Src) {
tmp_reg[0] = $Src;
- bf = (BifFunction) $Bif;
- $CALL_GUARD_BIF(bf, tmp_reg, $Dst);
-
- $FAIL($Fail);
}
-//
-// Guard BIF in body. It can fail like any BIF. No trace support.
-//
+i_bif.fetch1(Src) {
+ tmp_reg[1] = $Src;
+}
-i_bif1_body(Bif, Src, Dst) {
- ErtsBifFunc bf;
- Eterm tmp_reg[1];
+i_bif.fetch2(Src) {
+ tmp_reg[2] = $Src;
+}
- tmp_reg[0] = $Src;
+i_bif.call(Fail, Bif, Dst) {
bf = (BifFunction) $Bif;
$CALL_GUARD_BIF(bf, tmp_reg, $Dst);
- reg[0] = tmp_reg[0];
- SWAPOUT;
- I = handle_error(c_p, I, reg, ubif2mfa((void *) bf));
- goto post_error_handling;
-}
-
-//
-// Guard bif in guard with two arguments ('and'/2, 'or'/2, 'xor'/2).
-//
-
-i_bif2(Fail, Bif, Src1, Src2, Dst) {
- Eterm tmp_reg[2];
- ErtsBifFunc bf;
-
- tmp_reg[0] = $Src1;
- tmp_reg[1] = $Src2;
- bf = (ErtsBifFunc) $Bif;
- $CALL_GUARD_BIF(bf, tmp_reg, $Dst);
$FAIL($Fail);
}
//
-// Guard bif in body with two arguments ('and'/2, 'or'/2, 'xor'/2).
+// Guard BIF in body. It can fail like any BIF. No trace support.
//
-i_bif2_body(Bif, Src1, Src2, Dst) {
- Eterm tmp_reg[2];
- ErtsBifFunc bf;
-
- tmp_reg[0] = $Src1;
- tmp_reg[1] = $Src2;
- bf = (ErtsBifFunc) $Bif;
- $CALL_GUARD_BIF(bf, tmp_reg, $Dst);
- reg[0] = tmp_reg[0];
- reg[1] = tmp_reg[1];
- SWAPOUT;
- I = handle_error(c_p, I, reg, ubif2mfa((void *) bf));
- goto post_error_handling;
-}
-
-// Guard BIF in head (binary_part/3). On failure, ignore the error
-// and jump to the code for the next clause. We don't support tracing
-// of guard BIFs.
+i_bif1_body := i_bif_body.fetch0.call;
+i_bif2_body := i_bif_body.fetch1.fetch0.call;
+i_bif3_body := i_bif_body.fetch2.fetch1.fetch0.call;
-i_bif3(Fail, Bif, Src1, Src2, Src3, Dst) {
+i_bif_body.head() {
ErtsBifFunc bf;
Eterm tmp_reg[3];
+}
- tmp_reg[0] = $Src1;
- tmp_reg[1] = $Src2;
- tmp_reg[2] = $Src3;
- bf = (BifFunction) $Bif;
- $CALL_GUARD_BIF(bf, tmp_reg, $Dst);
-
- $FAIL($Fail);
+i_bif_body.fetch0(Src) {
+ tmp_reg[0] = $Src;
}
-// Guard BIF in body with three arguments (binary_part/3).
+i_bif_body.fetch1(Src) {
+ tmp_reg[1] = $Src;
+}
-i_bif3_body(Bif, Src1, Src2, Src3, Dst) {
- ErtsBifFunc bf;
- Eterm tmp_reg[3];
+i_bif_body.fetch2(Src) {
+ tmp_reg[2] = $Src;
+}
- tmp_reg[0] = $Src1;
- tmp_reg[1] = $Src2;
- tmp_reg[2] = $Src3;
+i_bif_body.call(Bif, Dst) {
bf = (BifFunction) $Bif;
$CALL_GUARD_BIF(bf, tmp_reg, $Dst);
+
reg[0] = tmp_reg[0];
reg[1] = tmp_reg[1];
+ reg[2] = tmp_reg[2];
SWAPOUT;
I = handle_error(c_p, I, reg, ubif2mfa((void *) bf));
goto post_error_handling;
diff --git a/erts/emulator/beam/ops.tab b/erts/emulator/beam/ops.tab
index fbed2e56e1..c657e9a1f9 100644
--- a/erts/emulator/beam/ops.tab
+++ b/erts/emulator/beam/ops.tab
@@ -1002,11 +1002,11 @@ bif1 Fail Bif=u$bif:erlang:get/1 Src=s Dst=d => gen_get(Src, Dst)
bif2 Jump=j u$bif:erlang:element/2 S1=s S2=xy Dst=d => gen_element(Jump, S1, S2, Dst)
-bif1 p Bif S1 Dst => i_bif1_body Bif S1 Dst
-bif1 Fail=f Bif S1 Dst => i_bif1 Fail Bif S1 Dst
+bif1 p Bif S1 Dst => i_bif1_body S1 Bif Dst
+bif1 Fail=f Bif S1 Dst => i_bif1 S1 Fail Bif Dst
-bif2 p Bif S1 S2 Dst => i_bif2_body Bif S1 S2 Dst
-bif2 Fail=f Bif S1 S2 Dst => i_bif2 Fail Bif S1 S2 Dst
+bif2 p Bif S1 S2 Dst => i_bif2_body S2 S1 Bif Dst
+bif2 Fail=f Bif S1 S2 Dst => i_bif2 S2 S1 Fail Bif Dst
i_get_hash c I d
i_get s d
@@ -1024,12 +1024,12 @@ i_fast_element xy j? I d
i_element xy j? s d
-i_bif1 f? b s d
-i_bif1_body b s d
-i_bif2 f? b s s d
-i_bif2_body b s s d
-i_bif3 f? b s s s d
-i_bif3_body b s s s d
+i_bif1 s f? b d
+i_bif1_body s b d
+i_bif2 s s f? b d
+i_bif2_body s s b d
+i_bif3 s s s f? b d
+i_bif3_body s s s b d
#
# Internal calls.
@@ -1590,14 +1590,14 @@ bif1 Fail u$bif:erlang:trunc/1 s d => too_old_compiler
#
# Guard BIFs.
#
-gc_bif1 p Live Bif Src Dst => i_bif1_body Bif Src Dst
-gc_bif1 Fail=f Live Bif Src Dst => i_bif1 Fail Bif Src Dst
+gc_bif1 p Live Bif Src Dst => i_bif1_body Src Bif Dst
+gc_bif1 Fail=f Live Bif Src Dst => i_bif1 Src Fail Bif Dst
-gc_bif2 p Live Bif S1 S2 Dst => i_bif2_body Bif S1 S2 Dst
-gc_bif2 Fail=f Live Bif S1 S2 Dst => i_bif2 Fail Bif S1 S2 Dst
+gc_bif2 p Live Bif S1 S2 Dst => i_bif2_body S2 S1 Bif Dst
+gc_bif2 Fail=f Live Bif S1 S2 Dst => i_bif2 S2 S1 Fail Bif Dst
-gc_bif3 p Live Bif S1 S2 S3 Dst => i_bif3_body Bif S1 S2 S3 Dst
-gc_bif3 Fail=f Live Bif S1 S2 S3 Dst => i_bif3 Fail Bif S1 S2 S3 Dst
+gc_bif3 p Live Bif S1 S2 S3 Dst => i_bif3_body S3 S2 S1 Bif Dst
+gc_bif3 Fail=f Live Bif S1 S2 S3 Dst => i_bif3 S3 S2 S1 Fail Bif Dst
#
# The following instruction is specially handled in beam_load.c