diff options
author | Björn Gustavsson <[email protected]> | 2016-02-04 07:25:50 +0100 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2016-02-25 14:53:11 +0100 |
commit | c634592019654ae801710665320d20c062252524 (patch) | |
tree | 3ba9c49c96a694cf8aeff0b8150606b3c6dea23b /lib/kernel/src | |
parent | 54debd4a9ce3afb680738179d29bafb43e2cba3b (diff) | |
download | otp-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/src')
-rw-r--r-- | lib/kernel/src/code_server.erl | 34 | ||||
-rw-r--r-- | lib/kernel/src/hipe_unified_loader.erl | 12 |
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, |