diff options
-rw-r--r-- | erts/emulator/beam/beam_emu.c | 2 | ||||
-rw-r--r-- | erts/emulator/beam/instrs.tab | 42 | ||||
-rw-r--r-- | erts/emulator/beam/ops.tab | 2 | ||||
-rwxr-xr-x | erts/emulator/utils/beam_makeops | 27 |
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 { |