⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 erl_db_util.c

📁 OTP是开放电信平台的简称
💻 C
📖 第 1 页 / 共 5 页
字号:
#endif#define FAIL_TERM am_EXIT /* The term to set as return when bif fails and			     do_catch != 0 */    *return_flags = 0U;restart:    ep = &term;    esp = mpsp->heap + prog->stack_offset;    sp = (Eterm **) esp;    hp = mpsp->heap;    ehp = mpsp->heap + prog->eheap_offset;    ret = am_true;    do_catch = 0;    fail_label = -1;    for (;;) {#ifdef DMC_DEBUG	if (*heap_fence != FENCE_PATTERN) {	    erl_exit(1, "Heap fence overwritten in db_prog_match after op "		     "0x%08x, overwritten with 0x%08x.", save_op, *heap_fence);	}	if (*eheap_fence != FENCE_PATTERN) {	    erl_exit(1, "Eheap fence overwritten in db_prog_match after op "		     "0x%08x, overwritten with 0x%08x.", save_op, 		     *eheap_fence);	}	if (*stack_fence != FENCE_PATTERN) {	    erl_exit(1, "Stack fence overwritten in db_prog_match after op "		     "0x%08x, overwritten with 0x%08x.", save_op, 		     *stack_fence);	}	save_op = *pc;#endif	switch (*pc++) {	case matchTryMeElse:	    n = *pc++;	    fail_label = prog->labels[n];	    break;	case matchArray: /* only when DCOMP_TRACE, is always first			    instruction. */	    n = *pc++;	    if ((int) n != arity)		FAIL();	    ep = (Eterm *) *ep;	    break;	case matchArrayBind: /* When the array size is unknown. */	    n = *pc++;	    hp[n] = dpm_array_to_list(psp, (Eterm *) term, arity);	    break;	case matchTuple: /* *ep is a tuple of arity n */	    if (!is_tuple(*ep))		FAIL();	    ep = tuple_val(*ep);	    n = *pc++;	    if (arityval(*ep) != n)		FAIL();	    ++ep;	    break;	case matchPushT: /* *ep is a tuple of arity n, 			    push ptr to first element */	    if (!is_tuple(*ep))		FAIL();	    tp = tuple_val(*ep);	    n = *pc++;	    if (arityval(*tp) != n)		FAIL();	    *sp++ = tp + 1;	    ++ep;	    break;	case matchList:	    if (!is_list(*ep))		FAIL();	    ep = list_val(*ep);	    break;	case matchPushL:	    if (!is_list(*ep))		FAIL();	    *sp++ = list_val(*ep);	    ++ep;	    break;	case matchPop:	    ep = *(--sp);	    break;	case matchBind:	    n = *pc++;	    hp[n] = *ep++;	    break;	case matchCmp:	    n = *pc++;	    if (!eq(hp[n],*ep))		FAIL();	    ++ep;	    break;	case matchEqBin:	    t = (Eterm) *pc++;	    if (!eq(*ep,t))		FAIL();	    ++ep;	    break;	case matchEqFloat:	    if (!is_float(*ep))		FAIL();	    if (memcmp(float_val(*ep) + 1, pc, sizeof(double)))		FAIL();	    pc += 2;	    ++ep;	    break;	case matchEqRef:	    if (!is_ref(*ep))		FAIL();	    if (!eq(*ep, make_internal_ref(pc)))		FAIL();	    i = thing_arityval(*pc);	    pc += i+1;	    ++ep;	    break;	case matchEqBig:	    if (!is_big(*ep))		FAIL();	    tp = big_val(*ep);	    if (*tp != *pc)		FAIL();	    i = BIG_ARITY(pc);	    while(i--)		if (*++tp != *++pc)		    FAIL();	    ++pc;	    ++ep;	    break;	case matchEq:	    t = (Eterm) *pc++; 	    if (t != *ep++)		FAIL();	    break;	case matchSkip:	    ++ep;	    break;	/* 	 * Here comes guard instructions 	 */	case matchPushC: /* Push constant */	    *esp++ = *pc++;	    break;	case matchConsA:	    ehp[1] = *--esp;	    ehp[0] = esp[-1];	    esp[-1] = make_list(ehp);	    ehp += 2;	    break;	case matchConsB:	    ehp[0] = *--esp;	    ehp[1] = esp[-1];	    esp[-1] = make_list(ehp);	    ehp += 2;	    break;	case matchMkTuple:	    n = *pc++;	    t = make_tuple(ehp);	    *ehp++ = make_arityval(n);	    while (n--) {		*ehp++ = *--esp;	    }	    *esp++ = t;	    break;	case matchCall0:	    bif = (Eterm (*)(Process*, ...)) *pc++;	    t = (*bif)(psp);	    if (is_non_value(t)) {		if (do_catch)		    t = FAIL_TERM;		else		    FAIL();	    }	    *esp++ = t;	    break;	case matchCall1:	    bif = (Eterm (*)(Process*, ...)) *pc++;	    t = (*bif)(psp, esp[-1]);	    if (is_non_value(t)) {		if (do_catch)		    t = FAIL_TERM;		else		    FAIL();	    }	    esp[-1] = t;	    break;	case matchCall2:	    bif = (Eterm (*)(Process*, ...)) *pc++;	    t = (*bif)(psp, esp[-1], esp[-2]);	    if (is_non_value(t)) {		if (do_catch)		    t = FAIL_TERM;		else		    FAIL();	    }	    --esp;	    esp[-1] = t;	    break;	case matchCall3:	    bif = (Eterm (*)(Process*, ...)) *pc++;	    t = (*bif)(psp, esp[-1], esp[-2], esp[-3]);	    if (is_non_value(t)) {		if (do_catch)		    t = FAIL_TERM;		else		    FAIL();	    }	    esp -= 2;	    esp[-1] = t;	    break;	case matchPushV:	    *esp++ = hp[*pc++];	    break;	case matchPushExpr:	    *esp++ = term;	    break;	case matchPushArrayAsList:	    n = arity; /* Only happens when 'term' is an array */	    tp = (Eterm *) term;	    *esp++  = make_list(ehp);	    while (n--) {		*ehp++ = *tp++;		*ehp = make_list(ehp + 1);		ehp++; /* As pointed out by Mikael Pettersson the expression			  (*ehp++ = make_list(ehp + 1)) that I previously			  had written here has undefined behaviour. */	    }	    ehp[-1] = NIL;	    break;	case matchPushArrayAsListU:	    /* This instruction is NOT efficient. */	    *esp++  = dpm_array_to_list(psp, (Eterm *) term, arity); 	    break;	case matchTrue:	    if (*--esp != am_true)		FAIL();	    break;	case matchOr:	    n = *pc++;	    t = am_false;	    while (n--) {		if (*--esp == am_true) {		    t = am_true;		} else if (*esp != am_false) {		    esp -= n;		    if (do_catch) {			t = FAIL_TERM;			break;		    } else {			FAIL();		    }		}	    }	    *esp++ = t;	    break;	case matchAnd:	    n = *pc++;	    t = am_true;	    while (n--) {		if (*--esp == am_false) {		    t = am_false;		} else if (*esp != am_true) {		    esp -= n;		    if (do_catch) {			t = FAIL_TERM;			break;		    } else {			FAIL();		    }		}	    }	    *esp++ = t;	    break;	case matchOrElse:	    n = *pc++;	    if (*--esp == am_true) {		++esp;		pc = (prog->text) + prog->labels[n];	    } else if (*esp != am_false) {		if (do_catch) {		    *esp++ = FAIL_TERM;		    pc = (prog->text) + prog->labels[n];;		} else {		    FAIL();		}	    }	    break;	case matchAndThen:	    n = *pc++;	    if (*--esp == am_false) {		esp++;		pc = (prog->text) + prog->labels[n];	    } else if (*esp != am_true) {		if (do_catch) {		    *esp++ = FAIL_TERM;		    pc = (prog->text) + prog->labels[n];;		} else {		    FAIL();		}	    }	    break;	case matchSelf:	    *esp++ = c_p->id;	    break;	case matchWaste:	    --esp;	    break;	case matchReturn:	    ret = *--esp;	    break;	case matchProcessDump: {	    erts_dsprintf_buf_t *dsbufp = erts_create_tmp_dsbuf(0);	    print_process_info(ERTS_PRINT_DSBUF, (void *) dsbufp, c_p);	    *esp++ = new_binary(psp, (byte *)dsbufp->str, (int)dsbufp->str_len);	    erts_destroy_tmp_dsbuf(dsbufp);	    break;	}	case matchDisplay: /* Debugging, not for production! */	    erts_printf("%T\n", esp[-1]);	    esp[-1] = am_true;	    break;	case matchSetReturnTrace:	    *return_flags |= MATCH_SET_RETURN_TRACE;	    *esp++ = am_true;	    break;	case matchSetExceptionTrace:	    *return_flags |= MATCH_SET_EXCEPTION_TRACE;	    *esp++ = am_true;	    break;	case matchIsSeqTrace:	    if (SEQ_TRACE_TOKEN(c_p) != NIL)		*esp++ = am_true;	    else		*esp++ = am_false;	    break;	case matchSetSeqToken:	    t = erts_seq_trace(c_p, esp[-1], esp[-2], 0);	    if (is_non_value(t)) {		esp[-2] = FAIL_TERM;	    } else {		esp[-2] = t;	    }	    --esp;	    break;	case matchSetSeqTokenFake:	    t = seq_trace_fake(c_p, esp[-1]);	    if (is_non_value(t)) {		esp[-2] = FAIL_TERM;	    } else {		esp[-2] = t;	    }	    --esp;	    break;	case matchGetSeqToken:	    if (SEQ_TRACE_TOKEN(c_p) == NIL) 		*esp++ = NIL;	    else { 		*esp++ = make_tuple(ehp); 		ehp[0] = make_arityval(5); 		ehp[1] = SEQ_TRACE_TOKEN_FLAGS(c_p); 		ehp[2] = SEQ_TRACE_TOKEN_LABEL(c_p); 		ehp[3] = SEQ_TRACE_TOKEN_SERIAL(c_p); 		ehp[4] = SEQ_TRACE_TOKEN_SENDER(c_p); 		ehp[5] = SEQ_TRACE_TOKEN_LASTCNT(c_p);		ASSERT(SEQ_TRACE_TOKEN_ARITY(c_p) == 5);		ASSERT(is_immed(ehp[1]));		ASSERT(is_immed(ehp[2]));		ASSERT(is_immed(ehp[3]));		ASSERT(is_immed(ehp[5]));		if(!is_immed(ehp[4])) {		    Eterm *sender = &ehp[4];		    ehp += 6;		    *sender = copy_struct(*sender,					  size_object(*sender),					  &ehp,					  &MSO(psp));		}		else		    ehp += 6;	    } 	    break;	case matchEnableTrace:	    if ( (n = erts_trace_flag2bit(esp[-1]))) {		BEGIN_ATOMIC_TRACE(c_p);		set_tracee_flags(c_p, c_p->tracer_proc, 0, n);		esp[-1] = am_true;	    } else {		esp[-1] = FAIL_TERM;	    }	    break;	case matchEnableTrace2:	    n = erts_trace_flag2bit((--esp)[-1]);	    esp[-1] = FAIL_TERM;	    if (n) {		BEGIN_ATOMIC_TRACE(c_p);		if ( (tmpp = get_proc(c_p, 0, esp[0], 0))) {		    /* Always take over the tracer of the current process */		    set_tracee_flags(tmpp, c_p->tracer_proc, 0, n);		    esp[-1] = am_true;		}	    }	    break;	case matchDisableTrace:	    if ( (n = erts_trace_flag2bit(esp[-1]))) {		BEGIN_ATOMIC_TRACE(c_p);		set_tracee_flags(c_p, c_p->tracer_proc, n, 0);		esp[-1] = am_true;	    } else {		esp[-1] = FAIL_TERM;	    }	    break;	case matchDisableTrace2:	    n = erts_trace_flag2bit((--esp)[-1]);	    esp[-1] = FAIL_TERM;	    if (n) {		BEGIN_ATOMIC_TRACE(c_p);		if ( (tmpp = get_proc(c_p, 0, esp[0], 0))) {		    /* Always take over the tracer of the current process */		    set_tracee_flags(tmpp, c_p->tracer_proc, n, 0);		    esp[-1] = am_true;		}	    }	    break; 	case matchCaller: 	    if (!(c_p->cp) || !(hp = find_function_from_pc(c_p->cp))) { 		*esp++ = am_undefined; 	    } else { 		*esp++ = make_tuple(ehp); 		ehp[0] = make_arityval(3); 		ehp[1] = hp[0]; 		ehp[2] = hp[1]; 		ehp[3] = make_small(hp[2]); 		ehp += 4; 	    } 	    break;	case matchSilent:	    --esp;	    if (*esp == am_true) {		erts_smp_proc_lock(c_p, ERTS_PROC_LOCKS_ALL_MINOR);		c_p->trace_flags |= F_TRACE_SILENT;		erts_smp_proc_unlock(c_p, ERTS_PROC_LOCKS_ALL_MINOR);	    }	    else if (*esp == am_false) {		erts_smp_proc_lock(c_p, ERTS_PROC_LOCKS_ALL_MINOR);		c_p->trace_flags &= ~F_TRACE_SILENT;		erts_smp_proc_unlock(c_p, ERTS_PROC_LOCKS_ALL_MINOR);	    }	    break;	case matchTrace2:	    {		/*    disable         enable                                */		Uint  d_flags  = 0,   e_flags  = 0;  /* process trace flags */		Eterm tracer = c_p->tracer_proc;		/* XXX Atomicity note: Not fully atomic. Default tracer		 * is sampled from current process but applied to		 * tracee and tracer later after releasing main		 * locks on current process, so c_p->tracer_proc		 * may actually have changed when tracee and tracer		 * gets updated. I do not think nobody will notice.		 * It is just the default value that is not fully atomic.		 * and the real argument settable from match spec		 * {trace,[],[{{tracer,Tracer}}]} is much, much older.		 */		int   cputs = 0;				if (! erts_trace_flags(esp[-1], &d_flags, &tracer, &cputs) ||		    ! erts_trace_flags(esp[-2], &e_flags, &tracer, &cputs) ||		    cputs ) {		    (--esp)[-1] = FAIL_TERM;		    break;		}		erts_smp_proc_lock(c_p, ERTS_PROC_LOCKS_ALL_MINOR);		(--esp)[-1] = set_match_trace(c_p, FAIL_TERM, tracer,					      d_flags, e_flags);		erts_smp_proc_unlock(c_p, ERTS_PROC_LOCKS_ALL_MINOR);	    }	    break;	case matchTrace3:	    {		/*    disable         enable                                */		Uint  d_flags  = 0,   e_flags  = 0;  /* process trace flags */		Eterm tracer = c_p->tracer_proc;		/* XXX Atomicity note. Not fully atomic. See above. 		 * Above it could possibly be solved, but not here.		 */		int   cputs = 0;		Eterm tracee = (--esp)[0];				if (! erts_trace_flags(esp[-1], &d_flags, &tracer, &cputs) ||		    ! erts_trace_flags(esp[-2], &e_flags, &tracer, &cputs) ||		    cputs ||		    ! (tmpp = get_proc(c_p, ERTS_PROC_LOCK_MAIN, 				       tracee, ERTS_PROC_LOCKS_ALL))) {		    (--esp)[-1] = FAIL_TERM;		    break;		}		if (tmpp == c_p) {		    (--esp)[-1] = set_match_trace(c_p, FAIL_TERM, tracer,						  d_flags, e_flags);		    erts_smp_proc_unlock(c_p, ERTS_PROC_LOCKS_ALL_MINOR);		} else {		    erts_smp_proc_unlock(c_p, ERTS_PROC_LOCK_MAIN);		    (--esp)[-1] = set_match_trace(tmpp, FAIL_TERM, tracer,						  d_flags, e_flags);		    erts_smp_proc_unlock(tmpp, ERTS_PROC_LOCKS_ALL);		    erts_smp_proc_lock(c_p, ERTS_PROC_LOCK_MAIN);		}	    }	    break;	case matchCatch:	    do_catch = 1;	    break;	case matchHalt:	    goto success;	default:	    erl_exit(1, "Internal error: unexpected opcode in match program.");	}    }fail:    *return_flags = 0U;    if (fail_label >= 0) { /* We failed during a "TryMeElse", 			      lets restart, with the next match 			      program */	pc = (prog->text) + fail_label;	cleanup_match_pseudo_process(mpsp, 1);	goto restart;    }    ret = THE_NON_VALUE;success:#ifdef DMC_DEBUG    if (*heap_fence != FENCE_PATTERN) {	erl_exit(1, "Heap fence overwritten in db_prog_match after op "		 "0x%08x, overwritten with 0x%08x.", save_op, *heap_fence);    }    if (*eheap_fence != FENCE_PATTERN) {	erl_exit(1, "Eheap fence overwritten in db_prog_match after op "		 "0x%08x, overwritten with 0x%08x.", save_op, 		 *eheap_fence);    }    if (*stack_fence != FENCE_PATTERN) {	erl_exit(1, "Stack fence overwritten in db_prog_match after op "		 "0x%08x, overwritten with 0x%08x.", save_op, 		 *stack_fence);    }#endif    esdp->current_process = current_scheduled;    END_ATOMIC_TRACE(c_p);    return ret;#undef FAIL#undef FAIL_TERM#undef BEGIN_ATOMIC_TRACE#undef END_ATOMIC_TRACE}/* * Convert a match program to a "magic" binary to return up to erlang

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -