From 49c136df375a5c9a831f044eb2e3fb3352429cee Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Wed, 30 Nov 2011 16:51:44 +0100 Subject: erts: Make erts_printf accept internal match states This is useful during debugging to prevent erts_printf from crashing when passed a match state term. --- erts/emulator/beam/erl_printf_term.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/erts/emulator/beam/erl_printf_term.c b/erts/emulator/beam/erl_printf_term.c index 34da9cab84..2320b64295 100644 --- a/erts/emulator/beam/erl_printf_term.c +++ b/erts/emulator/beam/erl_printf_term.c @@ -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>>"); -- cgit v1.2.3 From a17eaa7e2cc2f68fbc9bf5c924c5a230d650b9f1 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 1 Dec 2011 20:13:57 +0100 Subject: hipe,erts: Debug support for native call trace --- erts/emulator/hipe/hipe_bif2.c | 7 +++++++ erts/emulator/hipe/hipe_bif2.tab | 1 + erts/emulator/hipe/hipe_bif_list.m4 | 1 + erts/emulator/hipe/hipe_native_bif.h | 3 +++ erts/emulator/hipe/hipe_primops.h | 1 + lib/hipe/icode/hipe_beam_to_icode.erl | 32 ++++++++++++++++++++++++++++---- lib/hipe/icode/hipe_icode_primops.erl | 8 +++++++- lib/hipe/rtl/hipe_rtl_primops.erl | 2 ++ 8 files changed, 50 insertions(+), 5 deletions(-) diff --git a/erts/emulator/hipe/hipe_bif2.c b/erts/emulator/hipe/hipe_bif2.c index ee97541e15..4d42efc1cc 100644 --- a/erts/emulator/hipe/hipe_bif2.c +++ b/erts/emulator/hipe/hipe_bif2.c @@ -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); +} + diff --git a/erts/emulator/hipe/hipe_bif2.tab b/erts/emulator/hipe/hipe_bif2.tab index 51323ce7af..d43ee40c5d 100644 --- a/erts/emulator/hipe/hipe_bif2.tab +++ b/erts/emulator/hipe/hipe_bif2.tab @@ -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 diff --git a/erts/emulator/hipe/hipe_bif_list.m4 b/erts/emulator/hipe/hipe_bif_list.m4 index 942fa0c5cb..d9aa09b79e 100644 --- a/erts/emulator/hipe/hipe_bif_list.m4 +++ b/erts/emulator/hipe/hipe_bif_list.m4 @@ -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. diff --git a/erts/emulator/hipe/hipe_native_bif.h b/erts/emulator/hipe/hipe_native_bif.h index 9e3a156fbc..3f460a5a5c 100644 --- a/erts/emulator/hipe/hipe_native_bif.h +++ b/erts/emulator/hipe/hipe_native_bif.h @@ -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 */ diff --git a/erts/emulator/hipe/hipe_primops.h b/erts/emulator/hipe/hipe_primops.h index 38509c105b..52b4681cfe 100644 --- a/erts/emulator/hipe/hipe_primops.h +++ b/erts/emulator/hipe/hipe_primops.h @@ -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" diff --git a/lib/hipe/icode/hipe_beam_to_icode.erl b/lib/hipe/icode/hipe_beam_to_icode.erl index 2d2b414a70..35a8ce9cfe 100644 --- a/lib/hipe/icode/hipe_beam_to_icode.erl +++ b/lib/hipe/icode/hipe_beam_to_icode.erl @@ -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), diff --git a/lib/hipe/icode/hipe_icode_primops.erl b/lib/hipe/icode/hipe_icode_primops.erl index a413531c07..b0113fc556 100644 --- a/lib/hipe/icode/hipe_icode_primops.erl +++ b/lib/hipe/icode/hipe_icode_primops.erl @@ -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. diff --git a/lib/hipe/rtl/hipe_rtl_primops.erl b/lib/hipe/rtl/hipe_rtl_primops.erl index 5f273d8251..53aaa72aa6 100644 --- a/lib/hipe/rtl/hipe_rtl_primops.erl +++ b/lib/hipe/rtl/hipe_rtl_primops.erl @@ -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! _ -> -- cgit v1.2.3 From 02deff1b04a12be50e346c104e73a6841859d602 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 9 Feb 2012 16:31:59 +0100 Subject: hipe: Fix address_to_mfa in hipe loader Strange that the effect of this bug is not more fatal. Kudos to Fabian and Tom for spotting this one. --- lib/kernel/src/hipe_unified_loader.erl | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/lib/kernel/src/hipe_unified_loader.erl b/lib/kernel/src/hipe_unified_loader.erl index 1b56cd8d90..8010bc6a91 100644 --- a/lib/kernel/src/hipe_unified_loader.erl +++ b/lib/kernel/src/hipe_unified_loader.erl @@ -730,7 +730,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 +743,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. -- cgit v1.2.3 From 99c0207298251d5557335864f15547ca07a7b050 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 1 Dec 2011 20:20:09 +0100 Subject: hipe,erts: Add DEBUG support with MFA's in stack descriptors --- erts/emulator/hipe/hipe_stack.c | 10 +++++++++- erts/emulator/hipe/hipe_stack.h | 4 ++++ erts/emulator/hipe/hipe_x86_gc.h | 5 +++++ erts/emulator/hipe/hipe_x86_glue.h | 3 +++ lib/hipe/cerl/erl_bif_types.erl | 2 +- lib/kernel/src/hipe_unified_loader.erl | 8 +++++--- 6 files changed, 27 insertions(+), 5 deletions(-) diff --git a/erts/emulator/hipe/hipe_stack.c b/erts/emulator/hipe/hipe_stack.c index da462a64e1..53c316ba52 100644 --- a/erts/emulator/hipe/hipe_stack.c +++ b/erts/emulator/hipe/hipe_stack.c @@ -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; } diff --git a/erts/emulator/hipe/hipe_stack.h b/erts/emulator/hipe/hipe_stack.h index 4c14b4a519..f2dab4fbcf 100644 --- a/erts/emulator/hipe/hipe_stack.h +++ b/erts/emulator/hipe/hipe_stack.h @@ -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 */ }; diff --git a/erts/emulator/hipe/hipe_x86_gc.h b/erts/emulator/hipe/hipe_x86_gc.h index e4607ad27d..aa4abb6f59 100644 --- a/erts/emulator/hipe/hipe_x86_gc.h +++ b/erts/emulator/hipe/hipe_x86_gc.h @@ -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]; diff --git a/erts/emulator/hipe/hipe_x86_glue.h b/erts/emulator/hipe/hipe_x86_glue.h index b0db93267c..63ad250d60 100644 --- a/erts/emulator/hipe/hipe_x86_glue.h +++ b/erts/emulator/hipe/hipe_x86_glue.h @@ -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); diff --git a/lib/hipe/cerl/erl_bif_types.erl b/lib/hipe/cerl/erl_bif_types.erl index bb9dc44a0c..3d1e3e8137 100644 --- a/lib/hipe/cerl/erl_bif_types.erl +++ b/lib/hipe/cerl/erl_bif_types.erl @@ -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) -> diff --git a/lib/kernel/src/hipe_unified_loader.erl b/lib/kernel/src/hipe_unified_loader.erl index 8010bc6a91..cedaaf4f7e 100644 --- a/lib/kernel/src/hipe_unified_loader.erl +++ b/lib/kernel/src/hipe_unified_loader.erl @@ -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. -- cgit v1.2.3