aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--erts/emulator/beam/beam_emu.c2
-rw-r--r--erts/emulator/beam/instrs.tab42
-rw-r--r--erts/emulator/beam/ops.tab2
-rwxr-xr-xerts/emulator/utils/beam_makeops27
4 files changed, 48 insertions, 25 deletions
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c
index 7ef0772703..3dce16aedd 100644
--- a/erts/emulator/beam/beam_emu.c
+++ b/erts/emulator/beam/beam_emu.c
@@ -649,7 +649,7 @@ void process_main(Eterm * x_reg_array, FloatDef* f_reg_array)
* Note: c_p->arity must be set to reflect the number of useful terms in
* c_p->arg_reg before calling the scheduler.
*/
- if (!init_done) {
+ if (ERTS_UNLIKELY(!init_done)) {
/* This should only be reached during the init phase when only the main
* process is running. I.e. there is no race for init_done.
*/
diff --git a/erts/emulator/beam/instrs.tab b/erts/emulator/beam/instrs.tab
index 9c3e615cea..b79b960fd7 100644
--- a/erts/emulator/beam/instrs.tab
+++ b/erts/emulator/beam/instrs.tab
@@ -110,15 +110,11 @@ i_call_only(CallDest) {
$DISPATCH($CallDest);
}
-i_move_call_only(CallDest, Src) {
+move_call_only(Src, CallDest) {
x(0) = $Src;
$i_call_only($CallDest);
}
-move_call_only(Src, CallDest) {
- $i_move_call_only($CallDest, $Src);
-}
-
DISPATCHX(Dest) {
//| -no_next
DTRACE_GLOBAL_CALL_FROM_EXPORT(c_p, $Dest);
@@ -156,10 +152,10 @@ i_move_call_ext_last(Dest, StackOffset, Src) {
$i_call_ext_last($Dest, $StackOffset);
}
-APPLY(I, Deallocate) {
+APPLY(I, Deallocate, Next) {
//| -no_next
HEAVY_SWAPOUT;
- next = apply(c_p, reg, $I, $Deallocate);
+ $Next = apply(c_p, reg, $I, $Deallocate);
HEAVY_SWAPIN;
}
@@ -170,7 +166,7 @@ HANDLE_APPLY_ERROR() {
i_apply() {
BeamInstr *next;
- $APPLY(NULL, 0);
+ $APPLY(NULL, 0, next);
if (ERTS_LIKELY(next != NULL)) {
$i_call(next);
}
@@ -179,7 +175,7 @@ i_apply() {
i_apply_last(Deallocate) {
BeamInstr *next;
- $APPLY(I, $Deallocate);
+ $APPLY(I, $Deallocate, next);
if (ERTS_LIKELY(next != NULL)) {
$i_call_last(next, $Deallocate);
}
@@ -188,23 +184,23 @@ i_apply_last(Deallocate) {
i_apply_only() {
BeamInstr *next;
- $APPLY(I, 0);
+ $APPLY(I, 0, next);
if (ERTS_LIKELY(next != NULL)) {
$i_call_only(next);
}
$HANDLE_APPLY_ERROR();
}
-FIXED_APPLY(Arity, I, Deallocate) {
+FIXED_APPLY(Arity, I, Deallocate, Next) {
//| -no_next
HEAVY_SWAPOUT;
- next = fixed_apply(c_p, reg, $Arity, $I, $Deallocate);
+ $Next = fixed_apply(c_p, reg, $Arity, $I, $Deallocate);
HEAVY_SWAPIN;
}
apply(Arity) {
BeamInstr *next;
- $FIXED_APPLY($Arity, NULL, 0);
+ $FIXED_APPLY($Arity, NULL, 0, next);
if (ERTS_LIKELY(next != NULL)) {
$i_call(next);
}
@@ -213,16 +209,16 @@ apply(Arity) {
apply_last(Arity, Deallocate) {
BeamInstr *next;
- $FIXED_APPLY($Arity, I, $Deallocate);
+ $FIXED_APPLY($Arity, I, $Deallocate, next);
if (ERTS_LIKELY(next != NULL)) {
$i_call_last(next, $Deallocate);
}
$HANDLE_APPLY_ERROR();
}
-APPLY_FUN() {
+APPLY_FUN(Next) {
HEAVY_SWAPOUT;
- next = apply_fun(c_p, r(0), x(1), reg);
+ $Next = apply_fun(c_p, r(0), x(1), reg);
HEAVY_SWAPIN;
}
@@ -237,7 +233,7 @@ DISPATCH_FUN(I) {
i_apply_fun() {
BeamInstr *next;
- $APPLY_FUN();
+ $APPLY_FUN(next);
if (ERTS_LIKELY(next != NULL)) {
SET_CP(c_p, $NEXT_INSTRUCTION);
$DISPATCH_FUN(next);
@@ -247,7 +243,7 @@ i_apply_fun() {
i_apply_fun_last(Deallocate) {
BeamInstr *next;
- $APPLY_FUN();
+ $APPLY_FUN(next);
if (ERTS_LIKELY(next != NULL)) {
$deallocate($Deallocate);
$DISPATCH_FUN(next);
@@ -257,23 +253,23 @@ i_apply_fun_last(Deallocate) {
i_apply_fun_only() {
BeamInstr *next;
- $APPLY_FUN();
+ $APPLY_FUN(next);
if (ERTS_LIKELY(next != NULL)) {
$DISPATCH_FUN(next);
}
$HANDLE_APPLY_FUN_ERROR();
}
-CALL_FUN(Fun) {
+CALL_FUN(Fun, Next) {
//| -no_next
HEAVY_SWAPOUT;
- next = call_fun(c_p, $Fun, reg, THE_NON_VALUE);
+ $Next = call_fun(c_p, $Fun, reg, THE_NON_VALUE);
HEAVY_SWAPIN;
}
i_call_fun(Fun) {
BeamInstr *next;
- $CALL_FUN($Fun);
+ $CALL_FUN($Fun, next);
if (ERTS_LIKELY(next != NULL)) {
SET_CP(c_p, $NEXT_INSTRUCTION);
$DISPATCH_FUN(next);
@@ -283,7 +279,7 @@ i_call_fun(Fun) {
i_call_fun_last(Fun, Deallocate) {
BeamInstr *next;
- $CALL_FUN($Fun);
+ $CALL_FUN($Fun, next);
if (ERTS_LIKELY(next != NULL)) {
$deallocate($Deallocate);
$DISPATCH_FUN(next);
diff --git a/erts/emulator/beam/ops.tab b/erts/emulator/beam/ops.tab
index d848c1cceb..d64f6f2cfc 100644
--- a/erts/emulator/beam/ops.tab
+++ b/erts/emulator/beam/ops.tab
@@ -190,7 +190,9 @@ try Y F => catch Y F
try_case Y => try_end Y
try_end y
+%cold
try_case_end s
+%hot
# Destructive set tuple element
diff --git a/erts/emulator/utils/beam_makeops b/erts/emulator/utils/beam_makeops
index bcc92472d4..38754e67a1 100755
--- a/erts/emulator/utils/beam_makeops
+++ b/erts/emulator/utils/beam_makeops
@@ -1451,7 +1451,32 @@ sub expand_macro {
warn $@;
die "... from the body of $name at $where\n";
}
- ("do {\n$body\n} while (0)",$rest);
+ $body = "do {\n$body\n} while (0)"
+ if needs_do_wrapper($body);
+ ($body,$rest);
+}
+
+# Conservative heuristic to determine whether a do { ... } while(0)
+# wrapper is needed.
+sub needs_do_wrapper {
+ local $_ = shift;
+
+ s@^//[|][^\n]*\n@@;
+ s@^\s*@@s;
+ s@^/[*].*[*]/\s*@@s;
+ return 1 if /^(Eterm|Uint|Sint|int|unsigned)/; # Definitely needed.
+ return 0 if /^do/;
+ return 0 if /^SET_I/;
+ return 0 if /^SET_CP/;
+ return 0 if /^ERTS_NO_FPE_CHECK_INIT/;
+ return 0 if /^ASSERT/;
+ return 0 if /^DTRACE/;
+ return 0 if /^[A-Za-z_]*\s*=/;
+ return 0 if /^c_p->/;
+ return 0 if /^[A-Z_]*SWAPOUT/;
+ return 0 if /^if\s*[(]/;
+ return 0 if /^goto\b/;
+ return 1; # Not sure, say that it is needed.
}
sub do_pack {