Permalink
Browse files

Merge branch 'sverk/hipe-debug-cherries'

* sverk/hipe-debug-cherries:
  hipe,erts: Add DEBUG support with MFA's in stack descriptors
  hipe: Fix address_to_mfa in hipe loader
  hipe,erts: Debug support for native call trace
  erts: Make erts_printf accept internal match states
  • Loading branch information...
sverker committed Feb 23, 2012
2 parents 225da20 + 99c0207 commit 738c6d54dde1e4c8f6030690eabe50a287301eb9
@@ -437,7 +437,10 @@ print_term(fmtfn_t fn, void* arg, Eterm obj, long *dcount,
}
break;
case BINARY_DEF:
{
if (header_is_bin_matchstate(*boxed_val(wobj))) {
PRINT_STRING(res, fn, arg, "#MatchState");
}
else {
ProcBin* pb = (ProcBin *) binary_val(wobj);
if (pb->size == 1)
PRINT_STRING(res, fn, arg, "<<1 byte>>");
@@ -189,3 +189,10 @@ BIF_RETTYPE hipe_debug_bif_wrapper(BIF_ALIST_1)
#endif /* ERTS_ENABLE_LOCK_CHECK && ERTS_SMP */
BIF_RETTYPE hipe_bifs_debug_native_called_2(BIF_ALIST_2)
{
erts_printf("hipe_debug_native_called: %T(%T)\r\n", BIF_ARG_1, BIF_ARG_2);
BIF_RET(am_ok);
}
@@ -30,3 +30,4 @@ bif hipe_bifs:in_native/0
bif hipe_bifs:modeswitch_debug_on/0
bif hipe_bifs:modeswitch_debug_off/0
bif hipe_bifs:show_message_area/0
bif hipe_bifs:debug_native_called/2
@@ -165,6 +165,7 @@ gc_bif_interface_2(nbif_put_2, put_2)
gc_bif_interface_1(nbif_hipe_bifs_show_nstack_1, hipe_show_nstack_1)
gc_bif_interface_1(nbif_hipe_bifs_show_pcb_1, hipe_bifs_show_pcb_1)
gc_bif_interface_0(nbif_hipe_bifs_nstack_used_size_0, hipe_bifs_nstack_used_size_0)
gc_bif_interface_2(nbif_hipe_bifs_debug_native_called, hipe_bifs_debug_native_called_2)
/*
* Arithmetic operators called indirectly by the HiPE compiler.
@@ -110,6 +110,9 @@ int hipe_bs_put_big_integer(Eterm, Uint, byte*, unsigned, unsigned);
AEXTERN(Eterm,nbif_check_get_msg,(Process*));
Eterm hipe_check_get_msg(Process*);
AEXTERN(BIF_RETTYPE,nbif_hipe_bifs_debug_native_called,(Process*,Eterm,Eterm));
BIF_RETTYPE hipe_bifs_debug_native_called_2(BIF_ALIST_2);
/*
* SMP-specific stuff
*/
@@ -80,6 +80,7 @@ PRIMOP_LIST(am_fclearerror_error, &nbif_fclearerror_error)
#ifdef NO_FPE_SIGNALS
PRIMOP_LIST(am_emulate_fpe, &nbif_emulate_fpe)
#endif
PRIMOP_LIST(am_debug_native_called, &nbif_hipe_bifs_debug_native_called)
#if defined(__sparc__)
#include "hipe_sparc_primops.h"
@@ -130,7 +130,7 @@ struct sdesc *hipe_decode_sdesc(Eterm arg)
struct sdesc *sdesc;
if (is_not_tuple(arg) ||
(tuple_val(arg))[0] != make_arityval(5) ||
(tuple_val(arg))[0] != make_arityval(6) ||
term_to_Uint((tuple_val(arg))[1], &ra) == 0 ||
term_to_Uint((tuple_val(arg))[2], &exnra) == 0 ||
is_not_small((tuple_val(arg))[3]) ||
@@ -183,5 +183,13 @@ struct sdesc *hipe_decode_sdesc(Eterm arg)
off = unsigned_val(live[i]);
sdesc->livebits[off / 32] |= (1 << (off & 31));
}
#ifdef DEBUG
{
Eterm mfa_tpl = tuple_val(arg)[6];
sdesc->dbg_M = tuple_val(mfa_tpl)[1];
sdesc->dbg_F = tuple_val(mfa_tpl)[2];
sdesc->dbg_A = tuple_val(mfa_tpl)[3];
}
#endif
return sdesc;
}
@@ -35,6 +35,10 @@ struct sdesc {
struct sdesc *next; /* hash collision chain */
} bucket;
unsigned int summary; /* frame size, exn handler presence flag, arity */
#ifdef DEBUG
Eterm dbg_M, dbg_F;
unsigned dbg_A;
#endif
unsigned int livebits[1]; /* size depends on arch & data in summary field */
};
@@ -69,6 +69,11 @@ nstack_walk_init_sdesc(const Process *p, struct nstack_walk_state *state)
nstkarity = 0;
state->sdesc0[0].summary = (0 << 9) | (0 << 8) | nstkarity;
state->sdesc0[0].livebits[0] = 0;
# ifdef DEBUG
state->sdesc0[0].dbg_M = 0;
state->sdesc0[0].dbg_F = am_init;
state->sdesc0[0].dbg_A = 0;
# endif
/* XXX: this appears to prevent a gcc-4.1.1 bug on x86 */
__asm__ __volatile__("" : : "m"(*state) : "memory");
return &state->sdesc0[0];
@@ -62,6 +62,9 @@ static __inline__ void hipe_arch_glue_init(void)
.sdesc = {
.bucket = { .hvalue = (unsigned long)nbif_return },
.summary = (1<<8),
#ifdef DEBUG
.dbg_F = am_return,
#endif
},
};
hipe_init_sdesc_table(&nbif_return_sdesc.sdesc);
@@ -2381,7 +2381,7 @@ arg_types(hipe_bifs, check_crc, 1) ->
arg_types(hipe_bifs, enter_code, 2) ->
[t_binary(), t_sup(t_nil(), t_tuple())];
arg_types(hipe_bifs, enter_sdesc, 1) ->
[t_tuple([t_integer(), t_integer(), t_integer(), t_integer(), t_integer()])];
[t_tuple([t_integer(), t_integer(), t_integer(), t_integer(), t_integer(), t_mfa()])];
arg_types(hipe_bifs, find_na_or_make_stub, 2) ->
[t_mfa(), t_boolean()];
arg_types(hipe_bifs, fun_to_address, 1) ->
@@ -41,6 +41,9 @@
%%
%%-ifndef(DEBUG).
%%-define(DEBUG,6).
%% Choose one of two tracing methods
%%-define(DEBUG_BIF_CALL_TRACE,true).
%%-define(IO_FORMAT_CALL_TRACE,true).
%%-endif.
-include("../main/hipe.hrl").
@@ -51,8 +54,27 @@
-define(no_debug_msg(Str,Xs),ok).
%%-define(no_debug_msg(Str,Xs),msg(Str,Xs)).
-define(mk_debugcode(MFA, Env, Code),
case MFA of
-ifdef(DEBUG_BIF_CALL_TRACE).
%% Use BIF hipe_bifs_debug_native_called_2 to trace function calls
mk_debug_calltrace({_M,_F,A}=MFA, Env, Code) ->
MFAVar = mk_var(new),
Ignore = mk_var(new),
MkMfa = hipe_icode:mk_move(MFAVar,hipe_icode:mk_const(MFA)),
Args = [mk_var({x,I-1}) || I <- lists:seq(1,A)],
ArgTup = mk_var(new),
MkArgTup = hipe_icode:mk_primop([ArgTup], mktuple, Args),
Call = hipe_icode:mk_primop([Ignore], debug_native_called,
[MFAVar,ArgTup]),
{[MkMfa,MkArgTup,Call | Code], Env}.
-endif.
-ifdef(IO_FORMAT_CALL_TRACE).
%% Use io:format to trace function calls
mk_debug_calltrace(MFA, Env, Code) ->
case MFA of
{io,_,_} ->
%% We do not want to loop infinitely if we are compiling
%% the module io.
@@ -69,7 +91,9 @@
Call =
hipe_icode:mk_call([Ignore],io,format,[StringVar,MFAVar],remote),
{[MkMfa,MkString,Call | Code], Env}
end).
end.
-endif.
%%-----------------------------------------------------------------------
%% Exported types
@@ -127,7 +151,7 @@ trans_mfa_code(M,F,A, FunBeamCode, ClosureInfo) ->
MFA = {M,F,A},
%% Debug code
?IF_DEBUG_LEVEL(5,
{Code3,_Env3} = ?mk_debugcode(MFA, Env2, Code2),
{Code3,_Env3} = mk_debug_calltrace(MFA, Env1, Code2),
{Code3,_Env3} = {Code2,Env1}),
%% For stack optimization
Leafness = leafness(Code3),
@@ -137,7 +137,8 @@ is_safe({hipe_bs_primop, {bs_private_append, _, _}}) -> false;
is_safe({hipe_bs_primop, bs_init_writable}) -> true;
is_safe(#mkfun{}) -> true;
is_safe(#unsafe_element{}) -> true;
is_safe(#unsafe_update_element{}) -> true.
is_safe(#unsafe_update_element{}) -> true;
is_safe(debug_native_called) -> false.
-spec fails(icode_funcall()) -> boolean().
@@ -237,6 +238,7 @@ fails({hipe_bs_primop, bs_init_writable}) -> true;
fails(#mkfun{}) -> false;
fails(#unsafe_element{}) -> false;
fails(#unsafe_update_element{}) -> false;
fails(debug_native_called) -> false;
%% Apparently, we are calling fails/1 for all MFAs which are compiled.
%% This is weird and we should restructure the compiler to avoid
%% calling fails/1 for things that are not primops.
@@ -721,6 +723,8 @@ type(Primop, Args) ->
erl_types:t_any();
redtest ->
erl_types:t_any();
debug_native_called ->
erl_types:t_any();
{M, F, A} ->
erl_bif_types:type(M, F, A, Args)
end.
@@ -893,6 +897,8 @@ type(Primop) ->
erl_types:t_any();
redtest ->
erl_types:t_any();
debug_native_called ->
erl_types:t_any();
{M, F, A} ->
erl_bif_types:type(M, F, A)
end.
@@ -396,6 +396,8 @@ gen_primop({Op,Dst,Args,Cont,Fail}, IsGuard, ConstTab) ->
[Dst1]->
hipe_tagscheme:unsafe_tag_float(Dst1, Arg)
end;
debug_native_called ->
[hipe_rtl:mk_call(Dst, Op, Args, Cont, Fail, not_remote)];
%% Only names listed above are accepted! MFA:s are not primops!
_ ->
@@ -503,7 +503,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)
%% _ ->
@@ -516,14 +516,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.
@@ -730,7 +732,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 ->
@@ -743,11 +745,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.

0 comments on commit 738c6d5

Please sign in to comment.