aboutsummaryrefslogtreecommitdiffstats
path: root/lib/kernel
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2016-02-04 07:25:50 +0100
committerBjörn Gustavsson <[email protected]>2016-02-25 14:53:11 +0100
commitc634592019654ae801710665320d20c062252524 (patch)
tree3ba9c49c96a694cf8aeff0b8150606b3c6dea23b /lib/kernel
parent54debd4a9ce3afb680738179d29bafb43e2cba3b (diff)
downloadotp-c634592019654ae801710665320d20c062252524.tar.gz
otp-c634592019654ae801710665320d20c062252524.tar.bz2
otp-c634592019654ae801710665320d20c062252524.zip
Refactor post_beam_load handling
After loading a module without native code, it is still necessary to call hipe_unified_loader:post_beam_load() to ensure that any native calls to the module is done to the newly loaded module (and not to a previous version of the module in native code). Unfortunately, hipe_unified_loader:post_beam_load() can be slow and most of the time it doesn't do anything because no previous native code was loaded. Therefore, ad2962278f added a kludge using the process dictionary to avoid calling post_beam_load() if no native code at all has been loaded. Remove the kludge by keeping track exactly of which modules that have native code in the existing ets table. Also generalize post_beam_load() to handle severals modules at once, since we will soon need that functionality.
Diffstat (limited to 'lib/kernel')
-rw-r--r--lib/kernel/src/code_server.erl34
-rw-r--r--lib/kernel/src/hipe_unified_loader.erl12
2 files changed, 21 insertions, 25 deletions
diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl
index 09cf27d655..5c6464cd6c 100644
--- a/lib/kernel/src/code_server.erl
+++ b/lib/kernel/src/code_server.erl
@@ -32,8 +32,6 @@
-import(lists, [foreach/2]).
--define(ANY_NATIVE_CODE_LOADED, any_native_code_loaded).
-
-type on_load_item() :: {reference(),module(),file:name_all(),[pid()]}.
-record(state, {supervisor :: pid(),
@@ -91,8 +89,6 @@ init(Ref, Parent, [Root,Mode]) ->
namedb = init_namedb(Path),
mode = Mode},
- put(?ANY_NATIVE_CODE_LOADED, false),
-
Parent ! {Ref,{ok,self()}},
loop(State).
@@ -290,14 +286,14 @@ handle_call({load_binary,Mod,File,Bin}, Caller, S) when is_atom(Mod) ->
handle_call({load_native_partial,Mod,Bin}, {_From,_Tag}, S) ->
Architecture = erlang:system_info(hipe_architecture),
Result = (catch hipe_unified_loader:load(Mod, Bin, Architecture)),
- Status = hipe_result_to_status(Result),
+ Status = hipe_result_to_status(Result, S),
{reply,Status,S};
handle_call({load_native_sticky,Mod,Bin,WholeModule}, {_From,_Tag}, S) ->
Architecture = erlang:system_info(hipe_architecture),
Result = (catch hipe_unified_loader:load_module(Mod, Bin, WholeModule,
Architecture)),
- Status = hipe_result_to_status(Result),
+ Status = hipe_result_to_status(Result, S),
{reply,Status,S};
handle_call({ensure_loaded,Mod}, Caller, St) when is_atom(Mod) ->
@@ -1108,8 +1104,7 @@ try_load_module_2(File, Mod, Bin, Caller, Architecture,
#state{moddb=Db}=St) ->
case catch hipe_unified_loader:load_native_code(Mod, Bin, Architecture) of
{module,Mod} = Module ->
- put(?ANY_NATIVE_CODE_LOADED, true),
- ets:insert(Db, {Mod,File}),
+ ets:insert(Db, [{{native,Mod},true},{Mod,File}]),
{reply,Module,St};
no_native ->
try_load_module_3(File, Mod, Bin, Caller, Architecture, St);
@@ -1123,7 +1118,7 @@ try_load_module_3(File, Mod, Bin, Caller, Architecture,
case erlang:load_module(Mod, Bin) of
{module,Mod} = Module ->
ets:insert(Db, {Mod,File}),
- post_beam_load(Mod, Architecture),
+ post_beam_load([Mod], Architecture, St),
{reply,Module,St};
{error,on_load} ->
handle_on_load(Mod, File, Caller, St);
@@ -1132,23 +1127,24 @@ try_load_module_3(File, Mod, Bin, Caller, Architecture,
{reply,Error,St}
end.
-hipe_result_to_status(Result) ->
+hipe_result_to_status(Result, #state{moddb=Db}) ->
case Result of
- {module,_} ->
- put(?ANY_NATIVE_CODE_LOADED, true),
+ {module,Mod} ->
+ ets:insert(Db, [{{native,Mod},true}]),
Result;
_ ->
{error,Result}
end.
-post_beam_load(Mod, Architecture) ->
+post_beam_load(_, undefined, _) ->
+ %% HiPE is disabled.
+ ok;
+post_beam_load(Mods0, _Architecture, #state{moddb=Db}) ->
%% post_beam_load/2 can potentially be very expensive because it
- %% blocks multi-scheduling; thus we want to avoid the call if we
- %% know that it is not needed.
- case get(?ANY_NATIVE_CODE_LOADED) of
- true -> hipe_unified_loader:post_beam_load(Mod, Architecture);
- false -> ok
- end.
+ %% blocks multi-scheduling. Therefore, we only want to call
+ %% it with modules that are known to have native code loaded.
+ Mods = [M || M <- Mods0, ets:member(Db, {native,M})],
+ hipe_unified_loader:post_beam_load(Mods).
int_list([H|T]) when is_integer(H) -> int_list(T);
int_list([_|_]) -> false;
diff --git a/lib/kernel/src/hipe_unified_loader.erl b/lib/kernel/src/hipe_unified_loader.erl
index ddbbc548dd..73fcb2469c 100644
--- a/lib/kernel/src/hipe_unified_loader.erl
+++ b/lib/kernel/src/hipe_unified_loader.erl
@@ -44,7 +44,7 @@
-export([chunk_name/1,
%% Only the code and code_server modules may call the entries below!
load_native_code/3,
- post_beam_load/2,
+ post_beam_load/1,
load_module/4,
load/3]).
@@ -120,15 +120,15 @@ load_native_code(Mod, Bin, Architecture) when is_atom(Mod), is_binary(Bin) ->
%%========================================================================
--spec post_beam_load(atom(), hipe_architecture()) -> 'ok'.
+-spec post_beam_load([module()]) -> 'ok'.
-%% does nothing on a hipe-disabled system
-post_beam_load(_Mod, undefined) ->
+post_beam_load([])->
ok;
-post_beam_load(Mod, _) when is_atom(Mod) ->
+post_beam_load([_|_]=Mods) ->
erlang:system_flag(multi_scheduling, block),
try
- patch_to_emu(Mod)
+ _ = [patch_to_emu(Mod) || Mod <- Mods],
+ ok
after
erlang:system_flag(multi_scheduling, unblock)
end,