aboutsummaryrefslogtreecommitdiffstats
path: root/lib/kernel/src/hipe_unified_loader.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/kernel/src/hipe_unified_loader.erl')
-rw-r--r--lib/kernel/src/hipe_unified_loader.erl62
1 files changed, 48 insertions, 14 deletions
diff --git a/lib/kernel/src/hipe_unified_loader.erl b/lib/kernel/src/hipe_unified_loader.erl
index 8b3aa0286d..06d404905d 100644
--- a/lib/kernel/src/hipe_unified_loader.erl
+++ b/lib/kernel/src/hipe_unified_loader.erl
@@ -34,6 +34,13 @@
-module(hipe_unified_loader).
+-compile(no_native).
+% 'no_native' is a workaround to avoid "The code server called unloaded module"
+% caused by Mod:module_info(exports) in patch_to_emu_step1() called by post_beam_load.
+% Reproducable with hipelibs and asn1_SUITE.
+% I think the real solution would be to let BIF erlang:load_module/2 redirect all
+% hipe calls to the module and thereby remove post_beam_load.
+
-export([chunk_name/1,
%% Only the code and code_server modules may call the entries below!
load_native_code/2,
@@ -330,11 +337,16 @@ exports(ExportMap, BaseAddress) ->
exports(ExportMap, BaseAddress, [], []).
exports([Offset,M,F,A,IsClosure,IsExported|Rest], BaseAddress, MFAs, Addresses) ->
- MFA = {M,F,A},
- Address = BaseAddress + Offset,
- FunDef = #fundef{address=Address, mfa=MFA, is_closure=IsClosure,
- is_exported=IsExported},
- exports(Rest, BaseAddress, [MFA|MFAs], [FunDef|Addresses]);
+ case IsExported andalso erlang:is_builtin(M, F, A) of
+ true ->
+ exports(Rest, BaseAddress, MFAs, Addresses);
+ _false ->
+ MFA = {M,F,A},
+ Address = BaseAddress + Offset,
+ FunDef = #fundef{address=Address, mfa=MFA, is_closure=IsClosure,
+ is_exported=IsExported},
+ exports(Rest, BaseAddress, [MFA|MFAs], [FunDef|Addresses])
+ end;
exports([], _, MFAs, Addresses) ->
{MFAs, Addresses}.
@@ -498,7 +510,7 @@ patch_offset(Type, Data, Address, ConstAndZone, Addresses) ->
Atom = Data,
patch_atom(Address, Atom);
sdesc ->
- patch_sdesc(Data, Address, ConstAndZone);
+ patch_sdesc(Data, Address, ConstAndZone, Addresses);
x86_abs_pcrel ->
patch_instr(Address, Data, x86_abs_pcrel)
%% _ ->
@@ -511,14 +523,16 @@ patch_atom(Address, Atom) ->
patch_instr(Address, hipe_bifs:atom_to_word(Atom), atom).
patch_sdesc(?STACK_DESC(SymExnRA, FSize, Arity, Live),
- Address, {_ConstMap2,CodeAddress}) ->
+ Address, {_ConstMap2,CodeAddress}, _Addresses) ->
ExnRA =
case SymExnRA of
[] -> 0; % No catch
LabelOffset -> CodeAddress + LabelOffset
end,
?ASSERT(assert_local_patch(Address)),
- hipe_bifs:enter_sdesc({Address, ExnRA, FSize, Arity, Live}).
+ DBG_MFA = ?IF_DEBUG(address_to_mfa_lth(Address, _Addresses), {undefined,undefined,0}),
+ hipe_bifs:enter_sdesc({Address, ExnRA, FSize, Arity, Live, DBG_MFA}).
+
%%----------------------------------------------------------------
%% Handle a 'load_address'-type patch.
@@ -725,7 +739,7 @@ find_const(ConstNo, []) ->
%%
add_ref(CalleeMFA, Address, Addresses, RefType, Trampoline, RemoteOrLocal) ->
- CallerMFA = address_to_mfa(Address, Addresses),
+ CallerMFA = address_to_mfa_lth(Address, Addresses),
%% just a sanity assertion below
true = case RemoteOrLocal of
local ->
@@ -738,11 +752,31 @@ add_ref(CalleeMFA, Address, Addresses, RefType, Trampoline, RemoteOrLocal) ->
%% io:format("Adding ref ~w\n",[{CallerMFA, CalleeMFA, Address, RefType}]),
hipe_bifs:add_ref(CalleeMFA, {CallerMFA,Address,RefType,Trampoline,RemoteOrLocal}).
-address_to_mfa(Address, [#fundef{address=Adr, mfa=MFA}|_Rest]) when Address >= Adr -> MFA;
-address_to_mfa(Address, [_ | Rest]) -> address_to_mfa(Address, Rest);
-address_to_mfa(Address, []) ->
- ?error_msg("Local adddress not found ~w\n",[Address]),
- exit({?MODULE, local_address_not_found}).
+% For FunDefs sorted from low to high addresses
+address_to_mfa_lth(Address, FunDefs) ->
+ case address_to_mfa_lth(Address, FunDefs, false) of
+ false ->
+ ?error_msg("Local adddress not found ~w\n",[Address]),
+ exit({?MODULE, local_address_not_found});
+ MFA ->
+ MFA
+ end.
+
+address_to_mfa_lth(Address, [#fundef{address=Adr, mfa=MFA}|Rest], Prev) ->
+ if Address < Adr ->
+ Prev;
+ true ->
+ address_to_mfa_lth(Address, Rest, MFA)
+ end;
+address_to_mfa_lth(_Address, [], Prev) ->
+ Prev.
+
+% For FunDefs sorted from high to low addresses
+%% address_to_mfa_htl(Address, [#fundef{address=Adr, mfa=MFA}|_Rest]) when Address >= Adr -> MFA;
+%% address_to_mfa_htl(Address, [_ | Rest]) -> address_to_mfa_htl(Address, Rest);
+%% address_to_mfa_htl(Address, []) ->
+%% ?error_msg("Local adddress not found ~w\n",[Address]),
+%% exit({?MODULE, local_address_not_found}).
%%----------------------------------------------------------------
%% Change callers of the given module to instead trap to BEAM.