📄 erl_db_util.c
字号:
}, { am_is_function, &is_function_1, 1, DBIF_ALL }, { am_is_record, &is_record_3, 3, DBIF_ALL }, { am_abs, &abs_1, 1, DBIF_ALL }, { am_element, &element_2, 2, DBIF_ALL }, { am_hd, &hd_1, 1, DBIF_ALL }, { am_length, &length_1, 1, DBIF_ALL }, { am_node, &node_1, 1, DBIF_ALL }, { am_node, &node_0, 0, DBIF_ALL }, { am_round, &round_1, 1, DBIF_ALL }, { am_size, &size_1, 1, DBIF_ALL }, { am_bitsize, &bitsize_1, 1, DBIF_ALL }, { am_tl, &tl_1, 1, DBIF_ALL }, { am_trunc, &trunc_1, 1, DBIF_ALL }, { am_float, &float_1, 1, DBIF_ALL }, { am_Plus, &splus_1, 1, DBIF_ALL }, { am_Minus, &sminus_1, 1, DBIF_ALL }, { am_Plus, &splus_2, 2, DBIF_ALL }, { am_Minus, &sminus_2, 2, DBIF_ALL }, { am_Times, &stimes_2, 2, DBIF_ALL }, { am_Div, &div_2, 2, DBIF_ALL }, { am_div, &intdiv_2, 2, DBIF_ALL }, { am_rem, &rem_2, 2, DBIF_ALL }, { am_band, &band_2, 2, DBIF_ALL }, { am_bor, &bor_2, 2, DBIF_ALL }, { am_bxor, &bxor_2, 2, DBIF_ALL }, { am_bnot, &bnot_1, 1, DBIF_ALL }, { am_bsl, &bsl_2, 2, DBIF_ALL }, { am_bsr, &bsr_2, 2, DBIF_ALL }, { am_Gt, &sgt_2, 2, DBIF_ALL }, { am_Ge, &sge_2, 2, DBIF_ALL }, { am_Lt, &slt_2, 2, DBIF_ALL }, { am_Le, &sle_2, 2, DBIF_ALL }, { am_Eq, &seq_2, 2, DBIF_ALL }, { am_Eqeq, &seqeq_2, 2, DBIF_ALL }, { am_Neq, &sneq_2, 2, DBIF_ALL }, { am_Neqeq, &sneqeq_2, 2, DBIF_ALL }, { am_not, ¬_1, 1, DBIF_ALL }, { am_xor, &xor_2, 2, DBIF_ALL }, { am_get_tcw, &db_get_trace_control_word_0, 0, DBIF_TRACE_GUARD | DBIF_TRACE_BODY }, { am_set_tcw, &db_set_trace_control_word_1, 1, DBIF_TRACE_BODY }, { am_set_tcw_fake, &db_set_trace_control_word_fake_1, 1, DBIF_TRACE_BODY }};/*** Exported*/Eterm db_am_eot; /* Atom '$end_of_table' *//*** Forward decl's*//*** ... forwards for compiled matches*//* Utility code */static DMCGuardBif *dmc_lookup_bif(Eterm t, int arity);#ifdef DMC_DEBUGstatic Eterm dmc_lookup_bif_reversed(void *f);#endifstatic int cmp_uint(void *a, void *b);static int cmp_guard_bif(void *a, void *b);static int match_compact(ErlHeapFragment *expr, DMCErrInfo *err_info);static Uint my_size_object(Eterm t);static Eterm my_copy_struct(Eterm t, Eterm **hp, ErlOffHeap* off_heap);static Binary *allocate_magic_binary(size_t size);/* Guard compilation */static void do_emit_constant(DMCContext *context, DMC_STACK_TYPE(Uint) *text, Eterm t);static DMCRet dmc_list(DMCContext *context, DMCHeap *heap, DMC_STACK_TYPE(Uint) *text, Eterm t, int *constant);static DMCRet dmc_tuple(DMCContext *context, DMCHeap *heap, DMC_STACK_TYPE(Uint) *text, Eterm t, int *constant);static DMCRet dmc_variable(DMCContext *context, DMCHeap *heap, DMC_STACK_TYPE(Uint) *text, Eterm t, int *constant);static DMCRet dmc_fun(DMCContext *context, DMCHeap *heap, DMC_STACK_TYPE(Uint) *text, Eterm t, int *constant);static DMCRet dmc_expr(DMCContext *context, DMCHeap *heap, DMC_STACK_TYPE(Uint) *text, Eterm t, int *constant);static DMCRet compile_guard_expr(DMCContext *context, DMCHeap *heap, DMC_STACK_TYPE(Uint) *text, Eterm t);/* match expression subroutine */static DMCRet dmc_one_term(DMCContext *context, DMCHeap *heap, DMC_STACK_TYPE(Eterm) *stack, DMC_STACK_TYPE(Uint) *text, Eterm c);#ifdef DMC_DEBUGstatic int test_disassemble_next = 0;static void db_match_dis(Binary *prog);#define TRACE erts_fprintf(stderr,"Trace: %s:%d\n",__FILE__,__LINE__)#define FENCE_PATTERN_SIZE 1#define FENCE_PATTERN 0xDEADBEEFUL#else#define TRACE /* Nothing */#define FENCE_PATTERN_SIZE 0#endifstatic void add_dmc_err(DMCErrInfo *err_info, char *str, int variable, Eterm term, DMCErrorSeverity severity);static Eterm dpm_array_to_list(Process *psp, Eterm *arr, int arity);static Eterm match_spec_test(Process *p, Eterm against, Eterm spec, int trace);static Eterm seq_trace_fake(Process *p, Eterm arg1);/*** Interface routines.*//*** Pseudo BIF:s to be callable from the PAM VM.*/BIF_RETTYPE db_get_trace_control_word_0(Process *p) { Uint32 tcw = (Uint32) erts_smp_atomic_read(&trace_control_word); BIF_RET(erts_make_integer((Uint) tcw, p));}BIF_RETTYPE db_set_trace_control_word_1(Process *p, Eterm new) { Uint val; Uint32 old_tcw; if (!term_to_Uint(new, &val)) BIF_ERROR(p, BADARG); if (val != ((Uint32)val)) BIF_ERROR(p, BADARG); old_tcw = (Uint32) erts_smp_atomic_xchg(&trace_control_word, (long) val); BIF_RET(erts_make_integer((Uint) old_tcw, p));}static Eterm db_set_trace_control_word_fake_1(Process *p, Eterm new) { Uint val; if (!term_to_Uint(new, &val)) BIF_ERROR(p, BADARG); if (val != ((Uint32)val)) BIF_ERROR(p, BADARG); BIF_RET(db_get_trace_control_word_0(p));}/*** The API used by the tracer (declared in global.h):*//*** Matchexpr is a list of tuples containing match-code, i e:**** Matchexpr = [{Pattern, Guards, Body}, ...]** Pattern = [ PatternExpr , ...]** PatternExpr = Constant | PatternTuple | PatternList | Variable** Constant = Any erlang term** PatternTuple = { PatternExpr ... }** PatternList = [ PatternExpr ]** Variable = '$' ++ <number>** Guards = [Guard ...]** Guard = {GuardFunc, GuardExpr, ...}** GuardExpr = BoundVariable | Guard | GuardList | GuardTuple | ConstExpr** BoundVariable = Variable (existing in Pattern) ** GuardList = [ GuardExpr , ... ]** GuardTuple = {{ GuardExpr, ... }}** ConstExpr = {const, Constant}** GuardFunc = is_list | .... | element | ...** Body = [ BodyExpr, ... ]** BodyExpr = GuardExpr | { BodyFunc, GuardExpr, ... }** BodyFunc = return_trace | seq_trace | trace | ...** - or something like that...*/Eterm erts_match_set_get_source(Binary *mpsp){ MatchProg *prog = Binary2MatchProg(mpsp); return prog->saved_program;}/* This one is for the tracing */Binary *erts_match_set_compile(Process *p, Eterm matchexpr) { Binary *bin; Uint sz; Eterm *hp; bin = db_match_set_compile(p, matchexpr, DCOMP_TRACE); if (bin != NULL) { MatchProg *prog = Binary2MatchProg(bin); sz = size_object(matchexpr); prog->saved_program_buf = new_message_buffer(sz); hp = prog->saved_program_buf->mem; prog->saved_program = copy_struct(matchexpr, sz, &hp, &(prog->saved_program_buf->off_heap)); } return bin;}Binary *db_match_set_compile(Process *p, Eterm matchexpr, Uint flags) { Eterm l; Eterm t; Eterm l2; Eterm *tp; Eterm *hp; int n = 0; int num_heads; int i; Binary *mps = NULL; int compiled = 0; Eterm *matches,*guards, *bodies; Eterm *buff; Eterm sbuff[15]; if (!is_list(matchexpr)) return NULL; num_heads = 0; for (l = matchexpr; is_list(l); l = CDR(list_val(l))) ++num_heads; if (l != NIL) /* proper list... */ return NULL; if (num_heads > 5) { buff = erts_alloc(ERTS_ALC_T_DB_TMP, sizeof(Eterm) * num_heads * 3); } else { buff = sbuff; } matches = buff; guards = buff + num_heads; bodies = buff + (num_heads * 2); i = 0; for (l = matchexpr; is_list(l); l = CDR(list_val(l))) { t = CAR(list_val(l)); if (!is_tuple(t) || arityval((tp = tuple_val(t))[0]) != 3) { goto error; } if (!(flags & DCOMP_TRACE) || (!is_list(tp[1]) && !is_nil(tp[1]))) { t = tp[1]; } else { /* This is when tracing, the parameter is a list, that I convert to a tuple and that is matched against an array (strange, but gives the semantics of matching against a parameter list) */ n = 0; for (l2 = tp[1]; is_list(l2); l2 = CDR(list_val(l2))) { ++n; } if (l2 != NIL) { goto error; } hp = HAlloc(p, n + 1); t = make_tuple(hp); *hp++ = make_arityval((Uint) n); l2 = tp[1]; while (n--) { *hp++ = CAR(list_val(l2)); l2 = CDR(list_val(l2)); } } matches[i] = t; guards[i] = tp[2]; bodies[i] = tp[3]; ++i; } if ((mps = db_match_compile(matches, guards, bodies, num_heads, flags, NULL)) == NULL) { goto error; } compiled = 1; if (buff != sbuff) { erts_free(ERTS_ALC_T_DB_TMP, buff); } return mps;error: if (compiled) { erts_match_set_free(mps); } if (buff != sbuff) { erts_free(ERTS_ALC_T_DB_TMP, buff); } return NULL;}/* This is used when tracing */Eterm erts_match_set_lint(Process *p, Eterm matchexpr) { return db_match_set_lint(p, matchexpr, DCOMP_TRACE);}Eterm db_match_set_lint(Process *p, Eterm matchexpr, Uint flags) { Eterm l; Eterm t; Eterm l2; Eterm *tp; Eterm *hp; DMCErrInfo *err_info = db_new_dmc_err_info(); Eterm ret; int n = 0; int num_heads; Binary *mp; Eterm *matches,*guards, *bodies; Eterm sbuff[15]; Eterm *buff = sbuff; int i; if (!is_list(matchexpr)) { add_dmc_err(err_info, "Match programs are not in a list.", -1, 0UL, dmcError); goto done; } num_heads = 0; for (l = matchexpr; is_list(l); l = CDR(list_val(l))) ++num_heads; if (l != NIL) { /* proper list... */ add_dmc_err(err_info, "Match programs are not in a proper " "list.", -1, 0UL, dmcError); goto done; } if (num_heads > 5) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -