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

📄 hipe_bif0.c

📁 OTP是开放电信平台的简称
💻 C
📖 第 1 页 / 共 3 页
字号:
	    return p;    p = hipe_mfa_info_table_alloc(m, f, arity);    p->bucket.hvalue = h;    p->bucket.next = hipe_mfa_info_table.bucket[i];    hipe_mfa_info_table.bucket[i] = p;    hipe_mfa_info_table.used += 1;    size = 1 << hipe_mfa_info_table.log2size;    if( hipe_mfa_info_table.used > (4*size/5) )		/* rehash at 80% */	hipe_mfa_info_table_grow();    return p;}static void hipe_mfa_set_na(Eterm m, Eterm f, unsigned int arity, void *address, int is_exported){    struct hipe_mfa_info *p = hipe_mfa_info_table_put(m, f, arity);#ifdef DEBUG_LINKER    printf("%s: ", __FUNCTION__);    print_mfa(m, f, arity);    printf(": changing address from %p to %p\r\n", p->local_address, address);#endif    p->local_address = address;    if (is_exported)	p->remote_address = address;}#if defined(__powerpc__) || defined(__ppc__) || defined(__powerpc64__) || defined(__arm__)void *hipe_mfa_get_trampoline(Eterm m, Eterm f, unsigned int arity){    struct hipe_mfa_info *p = hipe_mfa_info_table_put(m, f, arity);    return p->trampoline;}void hipe_mfa_set_trampoline(Eterm m, Eterm f, unsigned int arity, void *trampoline){    struct hipe_mfa_info *p = hipe_mfa_info_table_put(m, f, arity);    p->trampoline = trampoline;}#endifBIF_RETTYPE hipe_bifs_set_funinfo_native_address_3(BIF_ALIST_3){    struct mfa mfa;    void *address;    int is_exported;    if (!term_to_mfa(BIF_ARG_1, &mfa))	BIF_ERROR(BIF_P, BADARG);    address = term_to_address(BIF_ARG_2);    if( !address )	BIF_ERROR(BIF_P, BADARG);    if (BIF_ARG_3 == am_true)	is_exported = 1;    else if (BIF_ARG_3 == am_false)	is_exported = 0;    else	BIF_ERROR(BIF_P, BADARG);    hipe_mfa_set_na(mfa.mod, mfa.fun, mfa.ari, address, is_exported);    BIF_RET(NIL);}BIF_RETTYPE hipe_bifs_invalidate_funinfo_native_addresses_1(BIF_ALIST_1){    Eterm lst;    struct mfa mfa;    struct hipe_mfa_info *p;    lst = BIF_ARG_1;    while (is_list(lst)) {	if (!term_to_mfa(CAR(list_val(lst)), &mfa))	    BIF_ERROR(BIF_P, BADARG);	lst = CDR(list_val(lst));	p = hipe_mfa_info_table_get(mfa.mod, mfa.fun, mfa.ari);	if (p) {	    p->remote_address = NULL;	    p->local_address = NULL;	    if (p->beam_code) {#ifdef DEBUG_LINKER		printf("%s: ", __FUNCTION__);		print_mfa(mfa.mod, mfa.fun, mfa.ari);		printf(": removing call trap from BEAM pc %p (new op %#lx)\r\n",		       p->beam_code, p->orig_beam_op);#endif		p->beam_code[0] = p->orig_beam_op;		p->beam_code = NULL;		p->orig_beam_op = 0;	    } else {#ifdef DEBUG_LINKER		printf("%s: ", __FUNCTION__);		print_mfa(mfa.mod, mfa.fun, mfa.ari);		printf(": no call trap to remove\r\n");#endif	    }	}    }    if (is_not_nil(lst))	BIF_ERROR(BIF_P, BADARG);    BIF_RET(NIL);}void hipe_mfa_save_orig_beam_op(Eterm mod, Eterm fun, unsigned int ari, Eterm *pc){    Uint orig_beam_op;    struct hipe_mfa_info *p;    orig_beam_op = pc[0];    if (orig_beam_op != BeamOpCode(op_hipe_trap_call_closure) &&	orig_beam_op != BeamOpCode(op_hipe_trap_call)) {	p = hipe_mfa_info_table_put(mod, fun, ari);#ifdef DEBUG_LINKER	printf("%s: ", __FUNCTION__);	print_mfa(mod, fun, ari);	printf(": saving orig op %#lx from BEAM pc %p\r\n", orig_beam_op, pc);#endif	p->beam_code = pc;	p->orig_beam_op = orig_beam_op;    } else {#ifdef DEBUG_LINKER	printf("%s: ", __FUNCTION__);	print_mfa(mod, fun, ari);	printf(": orig op %#lx already saved\r\n", orig_beam_op);#endif    }}static void *hipe_make_stub(Eterm m, Eterm f, unsigned int arity, int is_remote){    void *BEAMAddress;    void *StubAddress;#if 0    if( is_not_atom(m) || is_not_atom(f) || arity > 255 )	return NULL;#endif    BEAMAddress = hipe_get_emu_address(m, f, arity, is_remote);    StubAddress = hipe_make_native_stub(BEAMAddress, arity);#if 0    hipe_mfa_set_na(m, f, arity, StubAddress);#endif    return StubAddress;}static void *hipe_get_na_nofail(Eterm m, Eterm f, unsigned int a, int is_remote){    struct hipe_mfa_info *p;    void *address;    p = hipe_mfa_info_table_get(m, f, a);    if (p) {	/* find address, predicting for a runtime apply call */	address = p->remote_address;	if (!is_remote)	    address = p->local_address;	if (address)	    return address;	/* bummer, install stub, checking if one already existed */	address = p->remote_address;	if (address)	    return address;    } else {	p = hipe_mfa_info_table_put(m, f, a);    }    address = hipe_make_stub(m, f, a, is_remote);    /* XXX: how to tell if a BEAM MFA is exported or not? */    p->remote_address = address;    return address;}/* used for apply/3 in hipe_mode_switch */void *hipe_get_remote_na(Eterm m, Eterm f, unsigned int a){    if (is_not_atom(m) || is_not_atom(f) || a > 255)	return NULL;    return hipe_get_na_nofail(m, f, a, 1);}/* primop, but called like a BIF for error handling purposes */BIF_RETTYPE hipe_find_na_or_make_stub(BIF_ALIST_3){    Uint arity;    void *address;    if( is_not_atom(BIF_ARG_1) || is_not_atom(BIF_ARG_2) )	BIF_ERROR(BIF_P, BADARG);    arity = unsigned_val(BIF_ARG_3); /* no error check */    address = hipe_get_na_nofail(BIF_ARG_1, BIF_ARG_2, arity, 1);    BIF_RET((Eterm)address);	/* semi-Ok */}BIF_RETTYPE hipe_bifs_find_na_or_make_stub_2(BIF_ALIST_2){    struct mfa mfa;    void *address;    int is_remote;    if (!term_to_mfa(BIF_ARG_1, &mfa))	BIF_ERROR(BIF_P, BADARG);    if (BIF_ARG_2 == am_true)	is_remote = 1;    else if (BIF_ARG_2 == am_false)	is_remote = 0;    else	BIF_ERROR(BIF_P, BADARG);    address = hipe_get_na_nofail(mfa.mod, mfa.fun, mfa.ari, is_remote);    BIF_RET(address_to_term(address, BIF_P));}/* primop, but called like a BIF for error handling purposes */BIF_RETTYPE hipe_nonclosure_address(BIF_ALIST_2){    Eterm hdr, m, f;    void *address;    if (!is_boxed(BIF_ARG_1))	goto badfun;    hdr = *boxed_val(BIF_ARG_1);    if (is_export_header(hdr)) {	Export *ep = (Export*)(export_val(BIF_ARG_1)[1]);	unsigned int actual_arity = ep->code[2];	if (actual_arity != BIF_ARG_2)	    goto badfun;	m = ep->code[0];	f = ep->code[1];    } else if (hdr == make_arityval(2)) {	Eterm *tp = tuple_val(BIF_ARG_1);	m = tp[1];	f = tp[2];	if (is_not_atom(m) || is_not_atom(f))	    goto badfun;	if (!erts_find_export_entry(m, f, BIF_ARG_2))	    goto badfun;    } else	goto badfun;    address = hipe_get_na_nofail(m, f, BIF_ARG_2, 1);    BIF_RET((Eterm)address); badfun:    BIF_P->current = NULL;    BIF_P->fvalue = BIF_ARG_1;    BIF_ERROR(BIF_P, EXC_BADFUN);}/* * Patch Reference Handling. */struct hipe_mfa_info_list {    struct hipe_mfa_info *mfa;    struct hipe_mfa_info_list *next;};struct ref {    struct hipe_mfa_info *caller_mfa;    void *address;    void *trampoline;    unsigned int flags;    struct ref *next;};#define REF_FLAG_IS_LOAD_MFA		1	/* bit 0: 0 == call, 1 == load_mfa */#define REF_FLAG_IS_REMOTE		2	/* bit 1: 0 == local, 1 == remote */#define REF_FLAG_PENDING_REDIRECT	4	/* bit 2: 1 == pending redirect */#define REF_FLAG_PENDING_REMOVE		8	/* bit 3: 1 == pending remove *//* add_ref(CalleeMFA, {CallerMFA,Address,'call'|'load_mfa',Trampoline,'remote'|'local'}) */BIF_RETTYPE hipe_bifs_add_ref_2(BIF_ALIST_2){    struct mfa callee;    Eterm *tuple;    struct mfa caller;    void *address;    void *trampoline;    unsigned int flags;    struct hipe_mfa_info *callee_mfa;    struct hipe_mfa_info *caller_mfa;    struct hipe_mfa_info_list *refers_to;    struct ref *ref;    if (!term_to_mfa(BIF_ARG_1, &callee))	goto badarg;    if (is_not_tuple(BIF_ARG_2))	goto badarg;    tuple = tuple_val(BIF_ARG_2);    if (tuple[0] != make_arityval(5))	goto badarg;    if (!term_to_mfa(tuple[1], &caller))	goto badarg;    address = term_to_address(tuple[2]);    if (!address)	goto badarg;    switch (tuple[3]) {      case am_call:	flags = 0;	break;      case am_load_mfa:	flags = REF_FLAG_IS_LOAD_MFA;	break;      default:	goto badarg;    }    if (is_nil(tuple[4]))	trampoline = NULL;    else {	trampoline = term_to_address(tuple[4]);	if (!trampoline)	    goto badarg;    }    switch (tuple[5]) {      case am_local:	break;      case am_remote:	flags |= REF_FLAG_IS_REMOTE;	break;      default:	goto badarg;    }    callee_mfa = hipe_mfa_info_table_put(callee.mod, callee.fun, callee.ari);    caller_mfa = hipe_mfa_info_table_put(caller.mod, caller.fun, caller.ari);    refers_to = erts_alloc(ERTS_ALC_T_HIPE, sizeof(*refers_to));    refers_to->mfa = callee_mfa;    refers_to->next = caller_mfa->refers_to;    caller_mfa->refers_to = refers_to;    ref = erts_alloc(ERTS_ALC_T_HIPE, sizeof(*ref));    ref->caller_mfa = caller_mfa;    ref->address = address;    ref->trampoline = trampoline;    ref->flags = flags;    ref->next = callee_mfa->referred_from;    callee_mfa->referred_from = ref;    BIF_RET(NIL); badarg:    BIF_ERROR(BIF_P, BADARG);	}/* Given a CalleeMFA, mark each ref to it as pending-redirect. * This ensures that remove_refs_from() won't remove them: any * removal is instead done at the end of redirect_referred_from(). */BIF_RETTYPE hipe_bifs_mark_referred_from_1(BIF_ALIST_1) /* get_refs_from */{    struct mfa mfa;    const struct hipe_mfa_info *p;    struct ref *ref;    if (!term_to_mfa(BIF_ARG_1, &mfa))	BIF_ERROR(BIF_P, BADARG);    p = hipe_mfa_info_table_get(mfa.mod, mfa.fun, mfa.ari);    if (p)	for(ref = p->referred_from; ref != NULL; ref = ref->next)	    ref->flags |= REF_FLAG_PENDING_REDIRECT;    BIF_RET(NIL);}BIF_RETTYPE hipe_bifs_remove_refs_from_1(BIF_ALIST_1){    struct mfa mfa;    struct hipe_mfa_info *caller_mfa, *callee_mfa;    struct hipe_mfa_info_list *refers_to, *tmp_refers_to;    struct ref **prev, *ref;    if (!term_to_mfa(BIF_ARG_1, &mfa))	BIF_ERROR(BIF_P, BADARG);    caller_mfa = hipe_mfa_info_table_get(mfa.mod, mfa.fun, mfa.ari);    if (caller_mfa) {	refers_to = caller_mfa->refers_to;	while (refers_to) {	    callee_mfa = refers_to->mfa;	    prev = &callee_mfa->referred_from;	    ref = *prev;	    while (ref) {		if (ref->caller_mfa == caller_mfa) {		    if (ref->flags & REF_FLAG_PENDING_REDIRECT) {			ref->flags |= REF_FLAG_PENDING_REMOVE;			prev = &ref->next;			ref = ref->next;		    } else {			struct ref *tmp = ref;			ref = ref->next;			*prev = ref;			erts_free(ERTS_ALC_T_HIPE, tmp);		    }		} else {		    prev = &ref->next;		    ref = ref->next;		}	    }	    tmp_refers_to = refers_to;	    refers_to = refers_to->next;	    erts_free(ERTS_ALC_T_HIPE, tmp_refers_to);	}	caller_mfa->refers_to = NULL;    }    BIF_RET(NIL);}/* redirect_referred_from(CalleeMFA) * Redirect all pending-redirect refs in CalleeMFA's referred_from. * Then remove any pending-redirect && pending-remove refs from CalleeMFA's referred_from. */BIF_RETTYPE hipe_bifs_redirect_referred_from_1(BIF_ALIST_1){    struct mfa mfa;    struct hipe_mfa_info *p;    struct ref **prev, *ref;    int is_remote, res;    void *new_address;    if (!term_to_mfa(BIF_ARG_1, &mfa))	BIF_ERROR(BIF_P, BADARG);    p = hipe_mfa_info_table_get(mfa.mod, mfa.fun, mfa.ari);    if (p) {	prev = &p->referred_from;	ref = *prev;	while (ref) {	    if (ref->flags & REF_FLAG_PENDING_REDIRECT) {		is_remote = ref->flags & REF_FLAG_IS_REMOTE;		new_address = hipe_get_na_nofail(p->m, p->f, p->a, is_remote);		if (ref->flags & REF_FLAG_IS_LOAD_MFA)		    res = hipe_patch_insn(ref->address, (Uint)new_address, am_load_mfa);		else		    res = hipe_patch_call(ref->address, new_address, ref->trampoline);		if (res)		    fprintf(stderr, "%s: patch failed\r\n", __FUNCTION__);		ref->flags &= ~REF_FLAG_PENDING_REDIRECT;		if (ref->flags & REF_FLAG_PENDING_REMOVE) {		    struct ref *tmp = ref;		    ref = ref->next;		    *prev = ref;		    erts_free(ERTS_ALC_T_HIPE, tmp);		} else {		    prev = &ref->next;		    ref = ref->next;		}	    } else {		prev = &ref->next;		ref = ref->next;	    }	}    }    BIF_RET(NIL);}BIF_RETTYPE hipe_bifs_check_crc_1(BIF_ALIST_1){    Uint crc;    if (!term_to_Uint(BIF_ARG_1, &crc))	BIF_ERROR(BIF_P, BADARG);    if (crc == HIPE_SYSTEM_CRC)	BIF_RET(am_true);    BIF_RET(am_false);}BIF_RETTYPE hipe_bifs_system_crc_1(BIF_ALIST_1){    Uint crc;    if (!term_to_Uint(BIF_ARG_1, &crc))	BIF_ERROR(BIF_P, BADARG);    crc ^= (HIPE_SYSTEM_CRC ^ HIPE_LITERALS_CRC);    BIF_RET(Uint_to_term(crc, BIF_P));}BIF_RETTYPE hipe_bifs_get_rts_param_1(BIF_ALIST_1){    unsigned int is_defined;    unsigned long value;    if( is_not_small(BIF_ARG_1) )	BIF_ERROR(BIF_P, BADARG);    is_defined = 1;    value = 0;    switch( unsigned_val(BIF_ARG_1) ) {	RTS_PARAMS_CASES      default:	BIF_ERROR(BIF_P, BADARG);    }    if( !is_defined )	BIF_RET(NIL);    BIF_RET(Uint_to_term(value, BIF_P));}void hipe_patch_address(Uint *address, Eterm patchtype, Uint value){    switch( patchtype ) {      case am_load_fe:	hipe_patch_load_fe(address, value);	return;      default:	fprintf(stderr, "%s: unknown patchtype %#lx\r\n",		__FUNCTION__, patchtype);	return;    }}struct modinfo {    HashBucket bucket;		/* bucket.hvalue == atom_val(the module name) */    unsigned int code_size;};static Hash modinfo_table;static HashValue modinfo_hash(void *tmpl){    Eterm mod = (Eterm)tmpl;    return atom_val(mod);}static int modinfo_cmp(void *tmpl, void *bucket){    /* bucket->hvalue == modinfo_hash(tmpl), so just return 0 (match) */    return 0;}static void *modinfo_alloc(void *tmpl){    struct modinfo *p;    p = (struct modinfo*)erts_alloc(ERTS_ALC_T_HIPE, sizeof(*p));    p->code_size = 0;    return &p->bucket;}static void init_modinfo_table(void){    HashFunctions f;    static int init_done = 0;    if (init_done)	return;    init_done = 1;    f.hash = (H_FUN) modinfo_hash;    f.cmp = (HCMP_FUN) modinfo_cmp;    f.alloc = (HALLOC_FUN) modinfo_alloc;    f.free = (HFREE_FUN) NULL;    hash_init(ERTS_ALC_T_HIPE, &modinfo_table, "modinfo_table", 11, f);}BIF_RETTYPE hipe_bifs_update_code_size_3(BIF_ALIST_3){    struct modinfo *p;    Sint code_size;        init_modinfo_table();    if (is_not_atom(BIF_ARG_1) ||	is_not_small(BIF_ARG_3) ||	(code_size = signed_val(BIF_ARG_3)) < 0)	BIF_ERROR(BIF_P, BADARG);    p = (struct modinfo*)hash_put(&modinfo_table, (void*)BIF_ARG_1);    if (is_nil(BIF_ARG_2))	/* some MFAs, not whole module */	p->code_size += code_size;    else			/* whole module */	p->code_size = code_size;    BIF_RET(NIL);}BIF_RETTYPE hipe_bifs_code_size_1(BIF_ALIST_1){    struct modinfo *p;    unsigned int code_size;    init_modinfo_table();    if (is_not_atom(BIF_ARG_1))	BIF_ERROR(BIF_P, BADARG);    p = (struct modinfo*)hash_get(&modinfo_table, (void*)BIF_ARG_1);    code_size = p ? p->code_size : 0;    BIF_RET(make_small(code_size));}BIF_RETTYPE hipe_bifs_patch_insn_3(BIF_ALIST_3){    Uint *address, value;    address = term_to_address(BIF_ARG_1);    if (!address)	BIF_ERROR(BIF_P, BADARG);    if (!term_to_Uint(BIF_ARG_2, &value))	BIF_ERROR(BIF_P, BADARG);    if (hipe_patch_insn(address, value, BIF_ARG_3))	BIF_ERROR(BIF_P, BADARG);    BIF_RET(NIL);}BIF_RETTYPE hipe_bifs_patch_call_3(BIF_ALIST_3){    Uint *callAddress, *destAddress, *trampAddress;    callAddress = term_to_address(BIF_ARG_1);    if (!callAddress)	BIF_ERROR(BIF_P, BADARG);    destAddress = term_to_address(BIF_ARG_2);    if (!destAddress)	BIF_ERROR(BIF_P, BADARG);    if (is_nil(BIF_ARG_3))	trampAddress = NULL;    else {	trampAddress = term_to_address(BIF_ARG_3);	if (!trampAddress)	    BIF_ERROR(BIF_P, BADARG);    }    if (hipe_patch_call(callAddress, destAddress, trampAddress))	BIF_ERROR(BIF_P, BADARG);    BIF_RET(NIL);}

⌨️ 快捷键说明

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