summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/kernel/src/code.erl49
-rw-r--r--lib/kernel/src/code_server.erl109
2 files changed, 79 insertions, 79 deletions
diff --git a/lib/kernel/src/code.erl b/lib/kernel/src/code.erl
index acf145d59f..c56bbab4e5 100644
--- a/lib/kernel/src/code.erl
+++ b/lib/kernel/src/code.erl
@@ -184,7 +184,10 @@ objfile_extension() ->
-spec load_file(Module) -> load_ret() when
Module :: module().
load_file(Mod) when is_atom(Mod) ->
- call({load_file,Mod}).
+ case get_object_code(Mod) of
+ error -> {error,nofile};
+ {Mod,Binary,File} -> load_module(Mod, File, Binary, false)
+ end.
-spec ensure_loaded(Module) -> {module, Module} | {error, What} when
Module :: module(),
@@ -199,13 +202,24 @@ ensure_loaded(Mod) when is_atom(Mod) ->
-spec load_abs(Filename) -> load_ret() when
Filename :: file:filename().
load_abs(File) when is_list(File); is_atom(File) ->
- Mod = list_to_atom(filename:basename(File)),
- call({load_abs,File,Mod}).
+ load_abs(File, list_to_atom(filename:basename(File))).
%% XXX Filename is also an atom(), e.g. 'cover_compiled'
-spec load_abs(Filename :: loaded_filename(), Module :: module()) -> load_ret().
load_abs(File, M) when (is_list(File) orelse is_atom(File)), is_atom(M) ->
- call({load_abs,File,M}).
+ case modp(File) of
+ true ->
+ FileName0 = lists:concat([File, objfile_extension()]),
+ FileName = code_server:absname(FileName0),
+ case erl_prim_loader:get_file(FileName) of
+ {ok,Bin,_} ->
+ load_module(M, FileName, Bin, false);
+ error ->
+ {error, nofile}
+ end;
+ false ->
+ {error,badarg}
+ end.
%% XXX Filename is also an atom(), e.g. 'cover_compiled'
-spec load_binary(Module, Filename, Binary) ->
@@ -216,7 +230,26 @@ load_abs(File, M) when (is_list(File) orelse is_atom(File)), is_atom(M) ->
What :: badarg | load_error_rsn().
load_binary(Mod, File, Bin)
when is_atom(Mod), (is_list(File) orelse is_atom(File)), is_binary(Bin) ->
- call({load_binary,Mod,File,Bin}).
+ case modp(File) of
+ true -> load_module(Mod, File, Bin, true);
+ false -> {error,badarg}
+ end.
+
+load_module(Mod, File, Bin, Purge) ->
+ case erlang:prepare_loading(Mod, Bin) of
+ {error,_}=Error ->
+ Error;
+ Prepared ->
+ call({load_module, Prepared, Mod, File, Purge})
+ end.
+
+modp(Atom) when is_atom(Atom) -> true;
+modp(List) when is_list(List) -> int_list(List);
+modp(_) -> false.
+
+int_list([H|T]) when is_integer(H) -> int_list(T);
+int_list([_|_]) -> false;
+int_list([]) -> true.
-spec load_native_partial(Module :: module(), Binary :: binary()) -> load_ret().
load_native_partial(Mod, Bin) when is_atom(Mod), is_binary(Bin) ->
@@ -243,7 +276,8 @@ soft_purge(Mod) when is_atom(Mod) -> call({soft_purge,Mod}).
-spec is_loaded(Module) -> {'file', Loaded} | false when
Module :: module(),
Loaded :: loaded_filename().
-is_loaded(Mod) when is_atom(Mod) -> call({is_loaded,Mod}).
+is_loaded(Mod) when is_atom(Mod) ->
+ code_server:is_loaded(Mod).
-spec get_object_code(Module) -> {Module, Binary, Filename} | error when
Module :: module(),
@@ -346,7 +380,8 @@ unstick_mod(Mod) when is_atom(Mod) -> call({unstick_mod,Mod}).
-spec is_sticky(Module) -> boolean() when
Module :: module().
-is_sticky(Mod) when is_atom(Mod) -> call({is_sticky,Mod}).
+is_sticky(Mod) when is_atom(Mod) ->
+ code_server:is_sticky(Mod).
-spec set_path(Path) -> 'true' | {'error', What} when
Path :: [Dir :: file:filename()],
diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl
index af8531271f..8f0f9fba66 100644
--- a/lib/kernel/src/code_server.erl
+++ b/lib/kernel/src/code_server.erl
@@ -22,7 +22,8 @@
%% This file holds the server part of the code_server.
-export([start_link/1,
- call/1,
+ call/1, absname/1,
+ is_loaded/1, is_sticky/1,
system_code_change/4,
error_msg/2, info_msg/2
]).
@@ -31,6 +32,7 @@
-include_lib("stdlib/include/ms_transform.hrl").
-import(lists, [foreach/2]).
+-define(moddb, code_server).
-type on_load_action() ::
fun((term(), state()) -> {'reply',term(),state()} |
@@ -58,6 +60,14 @@ start_link(Args) ->
{Ref,Res} -> Res
end.
+is_loaded(Mod) ->
+ case ets:lookup(?moddb, Mod) of
+ [{Mod,File}] -> {file,File};
+ [] -> false
+ end.
+
+is_sticky(Mod) ->
+ is_sticky(Mod, ?moddb).
%% -----------------------------------------------------------
%% Init the code_server process.
@@ -67,7 +77,7 @@ init(Ref, Parent, [Root,Mode]) ->
register(?MODULE, self()),
process_flag(trap_exit, true),
- Db = ets:new(code, [private]),
+ Db = ets:new(?moddb, [named_table, protected]),
foreach(fun (M) ->
%% Pre-loaded modules are always sticky.
ets:insert(Db, [{M,preloaded},{{sticky,M},true}])
@@ -251,9 +261,6 @@ handle_call({dir,Dir}, _From, S) ->
Resp = do_dir(Root,Dir,S#state.namedb),
{reply,Resp,S};
-handle_call({load_file,Mod}, From, St) when is_atom(Mod) ->
- load_file(Mod, From, St);
-
handle_call({add_path,Where,Dir0}, _From,
#state{namedb=Namedb,path=Path0}=S) ->
{Resp,Path} = add_path(Where, Dir0, Path0, Namedb),
@@ -282,17 +289,12 @@ handle_call({replace_path,Name,Dir}, _From,
handle_call(get_path, _From, S) ->
{reply,S#state.path,S};
-%% Messages to load, delete and purge modules/files.
-handle_call({load_abs,File,Mod}, From, S) when is_atom(Mod) ->
- case modp(File) of
- false ->
- {reply,{error,badarg},S};
- true ->
- load_abs(File, Mod, From, S)
- end;
-
-handle_call({load_binary,Mod,File,Bin}, From, S) when is_atom(Mod) ->
- do_load_binary(Mod, File, Bin, From, S);
+handle_call({load_module,PC,Mod,File,Purge}, From, S) when is_atom(Mod) ->
+ case Purge andalso erlang:module_loaded(Mod) of
+ true -> do_purge(Mod);
+ false -> ok
+ end,
+ try_finish_module(File, Mod, PC, From, S);
handle_call({ensure_loaded,Mod}, From, St) when is_atom(Mod) ->
case erlang:module_loaded(Mod) of
@@ -319,9 +321,6 @@ handle_call({purge,Mod}, _From, St) when is_atom(Mod) ->
handle_call({soft_purge,Mod}, _From, St) when is_atom(Mod) ->
{reply,do_soft_purge(Mod),St};
-handle_call({is_loaded,Mod}, _From, St) when is_atom(Mod) ->
- {reply,is_loaded(Mod, St#state.moddb),St};
-
handle_call(all_loaded, _From, S) ->
Db = S#state.moddb,
{reply,all_loaded(Db),S};
@@ -332,10 +331,6 @@ handle_call({get_object_code,Mod}, _From, St) when is_atom(Mod) ->
Error -> {reply,Error,St}
end;
-handle_call({is_sticky, Mod}, _From, S) ->
- Db = S#state.moddb,
- {reply, is_sticky(Mod,Db), S};
-
handle_call(stop,_From, S) ->
{stop,normal,stopped,S};
@@ -1082,49 +1077,22 @@ add_paths(Where,[Dir|Tail],Path,NameDb) ->
add_paths(_,_,Path,_) ->
{ok,Path}.
-do_load_binary(Module, File, Binary, From, St) ->
- case modp(File) andalso is_binary(Binary) of
- true ->
- case erlang:module_loaded(Module) of
- true -> do_purge(Module);
- false -> ok
- end,
- try_load_module(File, Module, Binary, From, St);
- false ->
- {reply,{error,badarg},St}
- end.
-
-modp(Atom) when is_atom(Atom) -> true;
-modp(List) when is_list(List) -> int_list(List);
-modp(_) -> false.
-
-load_abs(File, Mod, From, St) ->
- Ext = objfile_extension(),
- FileName0 = lists:concat([File, Ext]),
- FileName = absname(FileName0),
- case erl_prim_loader:get_file(FileName) of
- {ok,Bin,_} ->
- try_load_module(FileName, Mod, Bin, From, St);
- error ->
- {reply,{error,nofile},St}
- end.
-
-try_load_module(File, Mod, Bin, From, St) ->
+try_finish_module(File, Mod, PC, From, St) ->
Action = fun(_, S) ->
- try_load_module_1(File, Mod, Bin, From, S)
+ try_finish_module_1(File, Mod, PC, From, S)
end,
handle_pending_on_load(Action, Mod, From, St).
-try_load_module_1(File, Mod, Bin, From, #state{moddb=Db}=St) ->
+try_finish_module_1(File, Mod, PC, From, #state{moddb=Db}=St) ->
case is_sticky(Mod, Db) of
true -> %% Sticky file reject the load
error_msg("Can't load module '~w' that resides in sticky dir\n",[Mod]),
{reply,{error,sticky_directory},St};
false ->
- try_load_module_2(File, Mod, Bin, From, undefined, St)
+ try_finish_module_2(File, Mod, PC, From, St)
end.
-try_load_module_2(File, Mod, Bin, From, _Architecture, St0) ->
+try_finish_module_2(File, Mod, PC, From, St0) ->
Action = fun({module,_}=Module, #state{moddb=Db}=S) ->
ets:insert(Db, {Mod,File}),
{reply,Module,S};
@@ -1134,7 +1102,12 @@ try_load_module_2(File, Mod, Bin, From, _Architecture, St0) ->
error_msg("Loading of ~ts failed: ~p\n", [File, What]),
{reply,Error,S}
end,
- Res = erlang:load_module(Mod, Bin),
+ Res = case erlang:finish_loading([PC]) of
+ ok ->
+ {module,Mod};
+ {Error,[Mod]} ->
+ {error,Error}
+ end,
handle_on_load(Res, Action, Mod, From, St0).
int_list([H|T]) when is_integer(H) -> int_list(T);
@@ -1147,23 +1120,22 @@ ensure_loaded(Mod, From, St0) ->
true ->
{reply,{module,Mod},S};
false ->
- load_file_1(Mod, From, S)
+ ensure_loaded_1(Mod, From, S)
end
end,
handle_pending_on_load(Action, Mod, From, St0).
-load_file(Mod, From, St0) ->
- Action = fun(_, S) ->
- load_file_1(Mod, From, S)
- end,
- handle_pending_on_load(Action, Mod, From, St0).
-
-load_file_1(Mod, From, St) ->
+ensure_loaded_1(Mod, From, St) ->
case get_object_code(St, Mod) of
error ->
{reply,{error,nofile},St};
{Mod,Binary,File} ->
- try_load_module_1(File, Mod, Binary, From, St)
+ case erlang:prepare_loading(Mod, Binary) of
+ {error, _} = Error ->
+ {reply, Error, St};
+ PC ->
+ try_finish_module_1(File, Mod, PC, From, St)
+ end
end.
get_object_code(#state{path=Path}, Mod) when is_atom(Mod) ->
@@ -1232,13 +1204,6 @@ absname_vr([[X, $:]|Name], _, _AbsBase) ->
end,
absname(filename:join(Name), Dcwd).
-
-is_loaded(M, Db) ->
- case ets:lookup(Db, M) of
- [{M,File}] -> {file,File};
- [] -> false
- end.
-
do_purge(Mod) ->
{_WasOld, DidKill} = erts_code_purger:purge(Mod),
DidKill.