diff options
author | Björn Gustavsson <[email protected]> | 2011-11-18 14:09:29 +0100 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2011-11-28 14:07:20 +0100 |
commit | 0aa3a8200025ae32c5aba11be5229fff19d03c7f (patch) | |
tree | 634d38bd382ff97593c7b198733bd4d14d9c3b02 /lib/hipe | |
parent | 02c869c58f226e8ea16de3d35e0e53d023376cb7 (diff) | |
download | otp-0aa3a8200025ae32c5aba11be5229fff19d03c7f.tar.gz otp-0aa3a8200025ae32c5aba11be5229fff19d03c7f.tar.bz2 otp-0aa3a8200025ae32c5aba11be5229fff19d03c7f.zip |
hipe: Remove single function compilation
Compiling single functions (as opposed to whole modules) to native
code complicates code management in HiPE. It would also vastly
complicate whole-module optimizations, such as returning multiple
return values instead of tuples within a module.
As a first step, remove the external interface for the single
compilation feature. In the future, there are many things that
could be restructured and simplified.
Diffstat (limited to 'lib/hipe')
-rw-r--r-- | lib/hipe/icode/hipe_beam_to_icode.erl | 61 | ||||
-rw-r--r-- | lib/hipe/main/hipe.erl | 129 | ||||
-rw-r--r-- | lib/hipe/tools/Makefile | 2 | ||||
-rw-r--r-- | lib/hipe/tools/hipe_ceach.erl | 74 |
4 files changed, 47 insertions, 219 deletions
diff --git a/lib/hipe/icode/hipe_beam_to_icode.erl b/lib/hipe/icode/hipe_beam_to_icode.erl index 45b390acbd..992f387bd5 100644 --- a/lib/hipe/icode/hipe_beam_to_icode.erl +++ b/lib/hipe/icode/hipe_beam_to_icode.erl @@ -31,7 +31,7 @@ -module(hipe_beam_to_icode). --export([module/2, mfa/3]). +-export([module/2]). %%----------------------------------------------------------------------- @@ -111,55 +111,6 @@ trans_beam_function_chunk(FunBeamCode, ClosureInfo) -> {MFA,Icode}. %%----------------------------------------------------------------------- -%% @doc -%% Translates the BEAM code of a single function into Icode. -%% Returns a tuple whose first argument is list of {{M,F,A}, ICode} -%% pairs, where the first entry is that of the given MFA, and the -%% following (in undefined order) are those of the funs that are -%% defined in the function, and recursively, in the funs. The -%% second argument of the tuple is the HiPE compiler options -%% contained in the file. -%% @end -%%----------------------------------------------------------------------- - --spec mfa(list(), mfa(), comp_options()) -> hipe_beam_to_icode_ret(). - -mfa(BeamFuns, {M,F,A} = MFA, Options) - when is_atom(M), is_atom(F), is_integer(A) -> - BeamCode0 = [beam_disasm:function__code(Fn) || Fn <- BeamFuns], - {ModCode, ClosureInfo} = preprocess_code(BeamCode0), - mfa_loop([MFA], [], sets:new(), ModCode, ClosureInfo, Options). - -mfa_loop([{M,F,A} = MFA | MFAs], Acc, Seen, ModCode, ClosureInfo, - Options) when is_atom(M), is_atom(F), is_integer(A) -> - case sets:is_element(MFA, Seen) of - true -> - mfa_loop(MFAs, Acc, Seen, ModCode, ClosureInfo, Options); - false -> - {Icode, FunMFAs} = mfa_get(M, F, A, ModCode, ClosureInfo, Options), - mfa_loop(FunMFAs ++ MFAs, [{MFA, Icode} | Acc], - sets:add_element(MFA, Seen), - ModCode, ClosureInfo, Options) - end; -mfa_loop([], Acc, _, _, _, _) -> - lists:reverse(Acc). - -mfa_get(M, F, A, ModCode, ClosureInfo, Options) -> - BeamCode = get_fun(ModCode, M,F,A), - pp_beam([BeamCode], Options), % cheat by using a list - Icode = trans_mfa_code(M,F,A, BeamCode, ClosureInfo), - FunMFAs = get_fun_mfas(BeamCode), - {Icode, FunMFAs}. - -get_fun_mfas([{patched_make_fun,{M,F,A} = MFA,_,_,_}|BeamCode]) - when is_atom(M), is_atom(F), is_integer(A) -> - [MFA|get_fun_mfas(BeamCode)]; -get_fun_mfas([_|BeamCode]) -> - get_fun_mfas(BeamCode); -get_fun_mfas([]) -> - []. - -%%----------------------------------------------------------------------- %% The main translation function. %%----------------------------------------------------------------------- @@ -1884,16 +1835,6 @@ find_mfa([{func_info,{atom,M},{atom,F},A}|_]) when is_atom(M), is_atom(F), is_integer(A), 0 =< A, A =< 255 -> {M, F, A}. -%%----------------------------------------------------------------------- - -%% Localize a particular function in a module -get_fun([[L, {func_info,{atom,M},{atom,F},A} | Is] | _], M,F,A) -> - [L, {func_info,{atom,M},{atom,F},A} | Is]; -get_fun([[_L1,_L2, {func_info,{atom,M},{atom,F},A} = MFA| _Is] | _], M,F,A) -> - ?WARNING_MSG("Consecutive labels found; please re-create the .beam file~n", []), - [_L1,_L2, MFA | _Is]; -get_fun([_|Rest], M,F,A) -> - get_fun(Rest, M,F,A). %%----------------------------------------------------------------------- %% Takes a list of arguments and returns the constants of them into diff --git a/lib/hipe/main/hipe.erl b/lib/hipe/main/hipe.erl index 570e4d9d17..e382085fa5 100644 --- a/lib/hipe/main/hipe.erl +++ b/lib/hipe/main/hipe.erl @@ -47,9 +47,8 @@ %% %% <h3>Using the direct interface - for advanced users only</h3> %% -%% To compile a module or a specific function to native code and -%% automatically load the code into memory, call <a -%% href="#c-1"><code>hipe:c(Module)</code></a> or <a +%% To compile a module to native code and automatically load the code +%% into memory, call <a href="#c-1"><code>hipe:c(Module)</code></a> or <a %% href="#c-2"><code>hipe:c(Module, Options)</code></a>. Note that all %% options are specific to the HiPE compiler. See the <a %% href="#index">function index</a> for other compiler functions. @@ -221,11 +220,10 @@ %%------------------------------------------------------------------- -type mod() :: atom(). --type c_unit() :: mod() | mfa(). -type f_unit() :: mod() | binary(). -type ret_rtl() :: [_]. --type c_ret() :: {'ok', c_unit()} | {'error', term()} | - {'ok', c_unit(), ret_rtl()}. %% The last for debugging only +-type c_ret() :: {'ok', mod()} | {'error', term()} | + {'ok', mod(), ret_rtl()}. %% The last for debugging only -type compile_file() :: atom() | string() | binary(). -type compile_ret() :: {hipe_architecture(), binary()} | list(). @@ -278,47 +276,44 @@ load(Mod, BeamFileName) when is_list(BeamFileName) -> end. %% @spec c(Name) -> {ok, Name} | {error, Reason} -%% Name = mod() | mfa() +%% Name = mod() %% Reason = term() %% %% @equiv c(Name, []) --spec c(c_unit()) -> c_ret(). +-spec c(mod()) -> c_ret(). c(Name) -> c(Name, []). %% @spec c(Name, options()) -> {ok, Name} | {error, Reason} -%% Name = mod() | mfa() +%% Name = mod() %% options() = [option()] %% option() = term() %% Reason = term() %% -%% @type mfa() = {M::mod(),F::fun(),A::arity()}. -%% A fully qualified function name. -%% %% @type fun() = atom(). A function identifier. %% %% @type arity() = integer(). A function arity; always nonnegative. %% %% @doc User-friendly native code compiler interface. Reads BEAM code -%% from the corresponding "Module<code>.beam</code>" file in the system -%% path, and compiles either a single function or the whole module to -%% native code. By default, the compiled code is loaded directly. See -%% above for documentation of options. +%% from the corresponding "Module<code>.beam</code>" file in the +%% system path, and compiles the whole module to native code. By +%% default, the compiled code is loaded directly. See above for +%% documentation of options. %% %% @see c/1 %% @see c/3 %% @see f/2 %% @see compile/2 --spec c(c_unit(), comp_options()) -> c_ret(). +-spec c(mod(), comp_options()) -> c_ret(). c(Name, Options) -> c(Name, beam_file(Name), Options). %% @spec c(Name, File, options()) -> {ok, Name} | {error, Reason} -%% Name = mod() | mfa() +%% Name = mod() %% File = filename() | binary() %% Reason = term() %% @@ -329,7 +324,6 @@ c(Name, Options) -> %% @see f/2 c(Name, File, Opts) -> - %% No server if only one function is compiled Opts1 = user_compile_opts(Opts), case compile(Name, File, Opts1) of {ok, Res} -> @@ -359,8 +353,7 @@ f(File) -> %% Reason = term() %% %% @doc Like <code>c/3</code>, but takes the module name from the -%% specified <code>File</code>. This always compiles the whole module; -%% there is no possibility to compile just a single function. +%% specified <code>File</code>. %% %% @see c/3 @@ -381,26 +374,26 @@ user_compile_opts(Opts) -> %% @spec compile(Name) -> {ok, {Target,Binary}} | {error, Reason} -%% Name = mod() | mfa() +%% Name = mod() %% Binary = binary() %% Reason = term() %% %% @equiv compile(Name, []) --spec compile(c_unit()) -> {'ok', compile_ret()} | {'error', term()}. +-spec compile(mod()) -> {'ok', compile_ret()} | {'error', term()}. compile(Name) -> compile(Name, []). %% @spec compile(Name, options()) -> {ok, {Target,Binary}} | {error, Reason} -%% Name = mod() | mfa() +%% Name = mod() %% Binary = binary() %% Reason = term() %% -%% @doc Direct compiler interface, for advanced use. This just compiles -%% the named function or module, reading BEAM code from the -%% corresponding "Module<code>.beam</code>" file in the system path. -%% Returns <code>{ok, Binary}</code> if successful, or <code>{error, +%% @doc Direct compiler interface, for advanced use. This just +%% compiles the module, reading BEAM code from the corresponding +%% "Module<code>.beam</code>" file in the system path. Returns +%% <code>{ok, Binary}</code> if successful, or <code>{error, %% Reason}</code> otherwise. By default, it does <em>not</em> load the %% binary to memory (the <code>load</code> option can be used to %% activate automatic loading). <code>File</code> can be either a file @@ -412,15 +405,13 @@ compile(Name) -> %% @see file/2 %% @see load/2 --spec compile(c_unit(), comp_options()) -> {'ok', compile_ret()} | {'error', _}. +-spec compile(mod(), comp_options()) -> {'ok', compile_ret()} | {'error', _}. compile(Name, Options) -> compile(Name, beam_file(Name), Options). --spec beam_file(mod() | mfa()) -> string(). +-spec beam_file(mod()) -> string(). -beam_file({M,F,A}) when is_atom(M), is_atom(F), is_integer(A), A >= 0 -> - beam_file(M); beam_file(Module) when is_atom(Module) -> case code:which(Module) of non_existing -> @@ -432,7 +423,7 @@ beam_file(Module) when is_atom(Module) -> %% @spec compile(Name, File, options()) -> %% {ok, {Target, Binary}} | {error, Reason} -%% Name = mod() | mfa() +%% Name = mod() %% File = filename() | binary() %% Binary = binary() %% Reason = term() @@ -442,18 +433,11 @@ beam_file(Module) when is_atom(Module) -> %% %% @see compile/2 --spec compile(c_unit(), compile_file(), comp_options()) -> +-spec compile(mod(), compile_file(), comp_options()) -> {'ok', compile_ret()} | {'error', term()}. -compile(Name, File, Opts0) -> - Opts1 = expand_kt2(Opts0), - Opts = - case Name of - {_Mod, _Fun, _Arity} -> - [no_concurrent_comp|Opts1]; - _ -> - Opts1 - end, +compile(Name, File, Opts0) when is_atom(Name) -> + Opts = expand_kt2(Opts0), case proplists:get_value(core, Opts) of true when is_binary(File) -> ?error_msg("Cannot get Core Erlang code from BEAM binary.",[]), @@ -486,23 +470,11 @@ compile(Name, File, Opts0) -> ?EXIT({cant_compile_source_code, Error}) end; Other when Other =:= false; Other =:= undefined -> - NewOpts = - case proplists:get_value(use_callgraph, Opts) of - No when No =:= false; No =:= undefined -> Opts; - _ -> - case Name of - {_M,_F,_A} -> - %% There is no point in using the callgraph or concurrent_comp - %% when analyzing just one function. - [no_use_callgraph, no_concurrent_comp|Opts]; - _ -> Opts - end - end, DisasmFun = fun (_) -> disasm(File) end, IcodeFun = fun (Code, Opts_) -> get_beam_icode(Name, Code, File, Opts_) end, - run_compiler(Name, DisasmFun, IcodeFun, NewOpts) + run_compiler(Name, DisasmFun, IcodeFun, Opts) end. -spec compile_core(mod(), cerl:c_module(), compile_file(), comp_options()) -> @@ -625,11 +597,6 @@ fix_beam_exports([{F,A,_}|BeamExports], Exports) -> fix_beam_exports([], Exports) -> Exports. -get_beam_icode({M,_F,_A} = MFA, {BeamCode, Exports}, _File, Options) -> - ?option_time({ok, Icode} = - (catch {ok, hipe_beam_to_icode:mfa(BeamCode, MFA, Options)}), - "BEAM-to-Icode", Options), - {{M, Exports, Icode}, false}; get_beam_icode(Mod, {BeamCode, Exports}, File, Options) -> ?option_time({ok, Icode} = (catch {ok, hipe_beam_to_icode:module(BeamCode, Options)}), @@ -899,7 +866,8 @@ maybe_load(Mod, Bin, WholeModule, Opts) -> do_load(Mod, Bin, WholeModule) end. -do_load(Mod, Bin, WholeModule) -> +do_load(Mod, Bin, BeamBinOrPath) when is_binary(BeamBinOrPath); + is_list(BeamBinOrPath) -> HostArch = get(hipe_host_arch), TargetArch = get(hipe_target_arch), %% Make sure we can do the load. @@ -907,29 +875,22 @@ do_load(Mod, Bin, WholeModule) -> ?EXIT({host_and_target_arch_differ, HostArch, TargetArch}); true -> ok end, - case WholeModule of + case code:is_sticky(Mod) of + true -> + %% We unpack and repack the Beam binary as a workaround to + %% ensure that it is not compressed. + {ok, _, Chunks} = beam_lib:all_chunks(BeamBinOrPath), + {ok, Beam} = beam_lib:build_module(Chunks), + %% Don't purge or register sticky mods; just load native. + code:load_native_sticky(Mod, Bin, Beam); false -> - %% In this case, the emulated code for the module must be loaded. - {module, Mod} = code:ensure_loaded(Mod), - code:load_native_partial(Mod, Bin); - BeamBinOrPath when is_binary(BeamBinOrPath) orelse is_list(BeamBinOrPath) -> - case code:is_sticky(Mod) of - true -> - %% We unpack and repack the Beam binary as a workaround to - %% ensure that it is not compressed. - {ok, _, Chunks} = beam_lib:all_chunks(WholeModule), - {ok, Beam} = beam_lib:build_module(Chunks), - %% Don't purge or register sticky mods; just load native. - code:load_native_sticky(Mod, Bin, Beam); - false -> - %% Normal loading of a whole module - Architecture = erlang:system_info(hipe_architecture), - ChunkName = hipe_unified_loader:chunk_name(Architecture), - {ok, _, Chunks0} = beam_lib:all_chunks(WholeModule), - Chunks = [{ChunkName, Bin}|lists:keydelete(ChunkName, 1, Chunks0)], - {ok, BeamPlusNative} = beam_lib:build_module(Chunks), - code:load_binary(Mod, code:which(Mod), BeamPlusNative) - end + %% Normal loading of a whole module + Architecture = erlang:system_info(hipe_architecture), + ChunkName = hipe_unified_loader:chunk_name(Architecture), + {ok, _, Chunks0} = beam_lib:all_chunks(BeamBinOrPath), + Chunks = [{ChunkName, Bin}|lists:keydelete(ChunkName, 1, Chunks0)], + {ok, BeamPlusNative} = beam_lib:build_module(Chunks), + code:load_binary(Mod, code:which(Mod), BeamPlusNative) end. assemble(CompiledCode, Closures, Exports, Options) -> diff --git a/lib/hipe/tools/Makefile b/lib/hipe/tools/Makefile index 0eaa3a7b05..e9745a6767 100644 --- a/lib/hipe/tools/Makefile +++ b/lib/hipe/tools/Makefile @@ -42,7 +42,7 @@ RELSYSDIR = $(RELEASE_PATH)/lib/hipe-$(VSN) # ---------------------------------------------------- # Target Specs # ---------------------------------------------------- -MODULES = hipe_tool hipe_profile hipe_ceach hipe_jit +MODULES = hipe_tool hipe_profile hipe_jit # hipe_timer HRL_FILES= diff --git a/lib/hipe/tools/hipe_ceach.erl b/lib/hipe/tools/hipe_ceach.erl deleted file mode 100644 index b29615e169..0000000000 --- a/lib/hipe/tools/hipe_ceach.erl +++ /dev/null @@ -1,74 +0,0 @@ -%% -*- erlang-indent-level: 2 -*- -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2002-2009. All Rights Reserved. -%% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%% -%% %CopyrightEnd% -%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% Copyright (c) 2001 by Erik Johansson. All Rights Reserved -%% ==================================================================== -%% Module : hipe_ceach -%% Purpose : Compile each function in a module, possibly applying a -%% fun between each compilation. Useful for bug hunting by -%% pinpointing a function that when compiled causes a bug. -%% Notes : -%% History : * 2001-12-11 Erik Johansson ([email protected]): Created. -%% ==================================================================== -%% Exports : -%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - --module(hipe_ceach). - --export([c/1, c/2, c/3]). - --include("../main/hipe.hrl"). - -%%--------------------------------------------------------------------- - --spec c(atom()) -> 'ok'. - -c(M) -> - lists:foreach(fun({F,A}) -> comp(M, F, A) end, - M:module_info(functions)). - --spec c(atom(), comp_options()) -> 'ok'. - -c(M, Opts) -> - lists:foreach(fun({F,A}) -> comp(M, F, A, Opts) end, - M:module_info(functions)). - --spec c(atom(), comp_options(), fun(() -> any())) -> 'ok'. - -c(M, Opts, Fn) -> - lists:foreach(fun({F,A}) -> comp(M, F, A, Opts), Fn() end, - M:module_info(functions)). - --spec comp(atom(), atom(), arity()) -> 'ok'. - -comp(M, F, A) -> - io:format("~w:~w/~w... ", [M, F, A]), - MFA = {M, F, A}, - {ok, MFA} = hipe:c(MFA), - io:format("OK\n"). - --spec comp(atom(), atom(), arity(), comp_options()) -> 'ok'. - -comp(M, F, A, Opts) -> - io:format("~w:~w/~w... ", [M, F, A]), - MFA = {M, F, A}, - {ok, MFA} = hipe:c(MFA, Opts), - io:format("OK\n"). |