📄 hipe_bif0.c
字号:
hipe_set_call_trap(pc, address, is_closure); BIF_RET(am_true);#endif }#ifdef DEBUG_LINKER printf("%s: ", __FUNCTION__); print_mfa(mfa.mod, mfa.fun, mfa.ari); printf(": no BEAM pc found\r\n");#endif BIF_RET(am_false);}#if 0 /* XXX: unused *//* * hipe_bifs_address_to_fun(Address) * - Address is the address of the start of a emu function's code * - returns {Module, Function, Arity} */BIF_RETTYPE hipe_bifs_address_to_fun_1(BIF_ALIST_1){ Eterm *pc; Eterm *funcinfo; Eterm *hp; pc = term_to_address(BIF_ARG_1); if( !pc ) BIF_ERROR(BIF_P, BADARG); funcinfo = find_function_from_pc(pc); if( !funcinfo ) BIF_RET(am_false); hp = HAlloc(BIF_P, 4); hp[0] = make_arityval(3); hp[1] = funcinfo[0]; hp[2] = funcinfo[1]; hp[3] = make_small(funcinfo[2]); BIF_RET(make_tuple(hp));}#endifBIF_RETTYPE hipe_bifs_enter_sdesc_1(BIF_ALIST_1){ struct sdesc *sdesc; sdesc = hipe_decode_sdesc(BIF_ARG_1); if( !sdesc ) { fprintf(stderr, "%s: bad sdesc!\r\n", __FUNCTION__); BIF_ERROR(BIF_P, BADARG); } if( hipe_put_sdesc(sdesc) != sdesc ) { fprintf(stderr, "%s: duplicate entry!\r\n", __FUNCTION__); BIF_ERROR(BIF_P, BADARG); } BIF_RET(NIL);}/* * Hash table mapping {M,F,A} to nbif address. */struct nbif { HashBucket bucket; Eterm mod; Eterm fun; unsigned arity; const void *address;};static struct nbif nbifs[BIF_SIZE] = {#define BIF_LIST(MOD,FUN,ARY,CFUN,IX) \ { {0,0}, MOD, FUN, ARY, &nbif_##CFUN },#include "erl_bif_list.h"#undef BIF_LIST};#define NBIF_HASH(m,f,a) ((m)*(f)+(a))static Hash nbif_table;static HashValue nbif_hash(struct nbif *x){ return NBIF_HASH(x->mod, x->fun, x->arity);}static int nbif_cmp(struct nbif *x, struct nbif *y){ return !(x->mod == y->mod && x->fun == y->fun && x->arity == y->arity);}static struct nbif *nbif_alloc(struct nbif *x){ return x; /* pre-allocated */}static void init_nbif_table(void){ HashFunctions f; int i; f.hash = (H_FUN) nbif_hash; f.cmp = (HCMP_FUN) nbif_cmp; f.alloc = (HALLOC_FUN) nbif_alloc; f.free = NULL; hash_init(ERTS_ALC_T_NBIF_TABLE, &nbif_table, "nbif_table", 500, f); for(i = 0; i < BIF_SIZE; ++i) hash_put(&nbif_table, &nbifs[i]);}static const void *nbif_address(Eterm mod, Eterm fun, unsigned arity){ struct nbif tmpl; struct nbif *nbif; tmpl.mod = mod; tmpl.fun = fun; tmpl.arity = arity; nbif = hash_get(&nbif_table, &tmpl); return nbif ? nbif->address : NULL;}/* * hipe_bifs_bif_address(M,F,A) -> address or false */BIF_RETTYPE hipe_bifs_bif_address_3(BIF_ALIST_3){ const void *address; static int init_done = 0; if( !init_done ) { init_nbif_table(); init_done = 1; } if( is_not_atom(BIF_ARG_1) || is_not_atom(BIF_ARG_2) || is_not_small(BIF_ARG_3) || signed_val(BIF_ARG_3) < 0 ) BIF_RET(am_false); address = nbif_address(BIF_ARG_1, BIF_ARG_2, unsigned_val(BIF_ARG_3)); if( address ) BIF_RET(address_to_term(address, BIF_P)); BIF_RET(am_false);}/* * Hash table mapping primops to their addresses. */struct primop { HashBucket bucket; /* bucket.hvalue == atom_val(name) */ const void *address;#if defined(__arm__) void *trampoline;#endif};static struct primop primops[] = {#define PRIMOP_LIST(ATOM,ADDRESS) { {0,_unchecked_atom_val(ATOM)}, ADDRESS },#include "hipe_primops.h"#undef PRIMOP_LIST};static Hash primop_table;static HashValue primop_hash(void *tmpl){ return ((struct primop*)tmpl)->bucket.hvalue; /* pre-initialised */}static int primop_cmp(void *tmpl, void *bucket){ return 0; /* hvalue matched so nothing further to do */}static void *primop_alloc(void *tmpl){ return tmpl; /* pre-allocated */}static void init_primop_table(void){ HashFunctions f; int i; static int init_done = 0; if (init_done) return; init_done = 1; f.hash = (H_FUN) primop_hash; f.cmp = (HCMP_FUN) primop_cmp; f.alloc = (HALLOC_FUN) primop_alloc; f.free = NULL; hash_init(ERTS_ALC_T_HIPE, &primop_table, "primop_table", 50, f); for(i = 0; i < sizeof(primops)/sizeof(primops[0]); ++i) hash_put(&primop_table, &primops[i]);}static struct primop *primop_table_get(Eterm name){ struct primop tmpl; init_primop_table(); tmpl.bucket.hvalue = atom_val(name); return hash_get(&primop_table, &tmpl);}#if defined(__arm__)static struct primop *primop_table_put(Eterm name){ struct primop tmpl; init_primop_table(); tmpl.bucket.hvalue = atom_val(name); return hash_put(&primop_table, &tmpl);}void *hipe_primop_get_trampoline(Eterm name){ struct primop *primop = primop_table_get(name); return primop ? primop->trampoline : NULL;}void hipe_primop_set_trampoline(Eterm name, void *trampoline){ struct primop *primop = primop_table_put(name); primop->trampoline = trampoline;}#endif/* * hipe_bifs_primop_address(Atom) -> address or false */BIF_RETTYPE hipe_bifs_primop_address_1(BIF_ALIST_1){ const struct primop *primop; if (is_not_atom(BIF_ARG_1)) BIF_RET(am_false); primop = primop_table_get(BIF_ARG_1); if (!primop) BIF_RET(am_false); BIF_RET(address_to_term(primop->address, BIF_P));}#if 0 /* XXX: unused *//* * hipe_bifs_gbif_address(F,A) -> address or false */#define GBIF_LIST(ATOM,ARY,CFUN) extern Eterm gbif_##CFUN(void);#include "hipe_gbif_list.h"#undef GBIF_LISTBIF_RETTYPE hipe_bifs_gbif_address_2(BIF_ALIST_2){ Uint arity; void *address; if( is_not_atom(BIF_ARG_1) || is_not_small(BIF_ARG_2) ) BIF_RET(am_false); /* error or false, does it matter? */ arity = signed_val(BIF_ARG_2); /* XXX: replace with a hash table later */ do { /* trick to let us use 'break' instead of 'goto' */#define GBIF_LIST(ATOM,ARY,CFUN) if(BIF_ARG_1 == ATOM && arity == ARY) { address = CFUN; break; }#include "hipe_gbif_list.h"#undef GBIF_LIST printf("\r\n%s: guard BIF ", __FUNCTION__); fflush(stdout); erts_printf("%T", BIF_ARG_1); printf("/%lu isn't listed in hipe_gbif_list.h\r\n", arity); BIF_RET(am_false); } while(0); BIF_RET(address_to_term(address, BIF_P));}#endifBIF_RETTYPE hipe_bifs_atom_to_word_1(BIF_ALIST_1){ if( is_not_atom(BIF_ARG_1) ) BIF_ERROR(BIF_P, BADARG); BIF_RET(Uint_to_term(BIF_ARG_1, BIF_P));}BIF_RETTYPE hipe_bifs_term_to_word_1(BIF_ALIST_1){ BIF_RET(Uint_to_term(BIF_ARG_1, BIF_P));}/* XXX: this is really a primop, not a BIF */BIF_RETTYPE hipe_conv_big_to_float(BIF_ALIST_1){ Eterm res; Eterm* hp; FloatDef f; if( is_not_big(BIF_ARG_1) ) { BIF_ERROR(BIF_P, BADARG); } if( big_to_double(BIF_ARG_1, &f.fd) < 0 ) { BIF_ERROR(BIF_P, BADARG); } hp = HAlloc(BIF_P, FLOAT_SIZE_OBJECT); res = make_float(hp); PUT_DOUBLE(f, hp); BIF_RET(res);}#if 0 /* XXX: unused *//* At least parts of this should be inlined in native code. The rest could be made a primop used by both the emulator and native code...*/BIF_RETTYPE hipe_bifs_make_fun_3(BIF_ALIST_3){ Eterm free_vars; Eterm mod; Eterm *tp; Uint index; Uint uniq; Uint num_free; Eterm tmp_var; Uint *tmp_ptr; unsigned needed; ErlFunThing *funp; Eterm *hp; int i; if (is_not_list(BIF_ARG_1) && is_not_nil(BIF_ARG_1)) { printf("Not a list\n"); BIF_ERROR(BIF_P, BADARG); } free_vars = BIF_ARG_1; if (is_not_atom(BIF_ARG_2)) { printf("Not an atom\n"); BIF_ERROR(BIF_P, BADARG); } mod = BIF_ARG_2; if (is_not_tuple(BIF_ARG_3) || (arityval(*tuple_val(BIF_ARG_3)) != 3 )) { printf("Not an good tuple\n"); BIF_ERROR(BIF_P, BADARG); } tp = tuple_val(BIF_ARG_3); if(term_to_Uint(tp[1], &index) == 0) { printf("Bad index\n"); BIF_ERROR(BIF_P, BADARG); } if(term_to_Uint(tp[2], &uniq) == 0){ printf("Bad unique\n"); BIF_ERROR(BIF_P, BADARG); } if(term_to_Uint(tp[3], &num_free) == 0){ printf("Bad num_free\n"); BIF_ERROR(BIF_P, BADARG); } needed = ERL_FUN_SIZE + num_free; funp = (ErlFunThing *) HAlloc(BIF_P, needed); hp = funp->env; funp->thing_word = HEADER_FUN; /* Need a ErlFunEntry* fe fe->refc++; funp->fe = fe; */ funp->num_free = num_free; funp->creator = BIF_P->id; for (i = 0; i < num_free; i++) { if (is_nil(free_vars)) { printf("to few free vars\n"); BIF_ERROR(BIF_P, BADARG); } tmp_ptr = list_val(free_vars); tmp_var = CAR(tmp_ptr); free_vars = CDR(tmp_ptr); *hp++ = tmp_var; } if (is_not_nil(free_vars)) { printf("to many free vars\n"); BIF_ERROR(BIF_P, BADARG); }#ifndef HYBRID /* FIND ME! */ funp->next = MSO(BIF_P).funs; MSO(BIF_P).funs = funp;#endif BIF_RET(make_fun(funp));}#endifBIF_RETTYPE hipe_bifs_make_fe_3(BIF_ALIST_3){ /* args: Nativecodeaddress, Module, {Uniq, Index, BeamAddress} */ Eterm mod; Uint index; Uint uniq; void *beam_address; ErlFunEntry* fe; Eterm *tp; void *native_address; native_address = term_to_address(BIF_ARG_1); if( !native_address ) BIF_ERROR(BIF_P, BADARG); if (is_not_atom(BIF_ARG_2)) { BIF_ERROR(BIF_P, BADARG); } mod = BIF_ARG_2; if (is_not_tuple(BIF_ARG_3) || (arityval(*tuple_val(BIF_ARG_3)) != 3 )) { BIF_ERROR(BIF_P, BADARG); } tp = tuple_val(BIF_ARG_3); if(term_to_Uint(tp[1], &uniq) == 0){ printf("Bad unique\n"); BIF_ERROR(BIF_P, BADARG); } if(term_to_Uint(tp[2], &index) == 0) { printf("Bad index\n"); BIF_ERROR(BIF_P, BADARG); } beam_address = term_to_address(tp[3]); if( !beam_address ) BIF_ERROR(BIF_P, BADARG); fe = erts_get_fun_entry(mod, uniq, index); if (fe == NULL) { int i = atom_val(mod); char atom_buf[256]; atom_buf[0] = '\0'; strncat(atom_buf, (char*)atom_tab(i)->name, atom_tab(i)->len); printf("no fun entry for %s %ld:%ld\n", atom_buf, uniq, index); BIF_ERROR(BIF_P, BADARG); } fe->native_address = native_address; if (erts_refc_dectest(&fe->refc, 0) == 0) erts_erase_fun_entry(fe); BIF_RET(address_to_term((void *)fe, BIF_P));}#if 0 /* XXX: unused */BIF_RETTYPE hipe_bifs_make_native_stub_2(BIF_ALIST_2){ void *beamAddress; Uint beamArity; void *stubAddress; if( (beamAddress = term_to_address(BIF_ARG_1)) == 0 || is_not_small(BIF_ARG_2) || (beamArity = unsigned_val(BIF_ARG_2)) >= 256 ) BIF_ERROR(BIF_P, BADARG); stubAddress = hipe_make_native_stub(beamAddress, beamArity); BIF_RET(address_to_term(stubAddress, BIF_P));}#endif/* * MFA info hash table: * - maps MFA to native code entry point * - the MFAs it calls (refers_to) * - the references to it (referred_from) * - maps MFA to most recent trampoline [if powerpc or arm] */struct hipe_mfa_info { struct { unsigned long hvalue; struct hipe_mfa_info *next; } bucket; Eterm m; /* atom */ Eterm f; /* atom */ unsigned int a; void *remote_address; void *local_address; Eterm *beam_code; Uint orig_beam_op; struct hipe_mfa_info_list *refers_to; struct ref *referred_from;#if defined(__powerpc__) || defined(__ppc__) || defined(__powerpc64__) || defined(__arm__) void *trampoline;#endif};static struct { unsigned int log2size; unsigned int mask; /* INV: mask == (1 << log2size)-1 */ unsigned int used; struct hipe_mfa_info **bucket;} hipe_mfa_info_table;#define HIPE_MFA_HASH(M,F,A) ((M) * (F) + (A))static struct hipe_mfa_info **hipe_mfa_info_table_alloc_bucket(unsigned int size){ unsigned long nbytes = size * sizeof(struct hipe_mfa_info*); struct hipe_mfa_info **bucket = erts_alloc(ERTS_ALC_T_HIPE, nbytes); sys_memzero(bucket, nbytes); return bucket;}static void hipe_mfa_info_table_grow(void){ unsigned int old_size, new_size, new_mask; struct hipe_mfa_info **old_bucket, **new_bucket; unsigned int i; old_size = 1 << hipe_mfa_info_table.log2size; hipe_mfa_info_table.log2size += 1; new_size = 1 << hipe_mfa_info_table.log2size; new_mask = new_size - 1; hipe_mfa_info_table.mask = new_mask; old_bucket = hipe_mfa_info_table.bucket; new_bucket = hipe_mfa_info_table_alloc_bucket(new_size); hipe_mfa_info_table.bucket = new_bucket; for(i = 0; i < old_size; ++i) { struct hipe_mfa_info *b = old_bucket[i]; while( b != NULL ) { struct hipe_mfa_info *next = b->bucket.next; unsigned int j = b->bucket.hvalue & new_mask; b->bucket.next = new_bucket[j]; new_bucket[j] = b; b = next; } } erts_free(ERTS_ALC_T_HIPE, old_bucket);}static struct hipe_mfa_info *hipe_mfa_info_table_alloc(Eterm m, Eterm f, unsigned int arity){ struct hipe_mfa_info *res; res = (struct hipe_mfa_info*)erts_alloc(ERTS_ALC_T_HIPE, sizeof(*res)); res->m = m; res->f = f; res->a = arity; res->remote_address = NULL; res->local_address = NULL; res->beam_code = NULL; res->orig_beam_op = 0; res->refers_to = NULL; res->referred_from = NULL;#if defined(__powerpc__) || defined(__ppc__) || defined(__powerpc64__) || defined(__arm__) res->trampoline = NULL;#endif return res;}void hipe_mfa_info_table_init(void){ unsigned int log2size, size; log2size = 10; size = 1 << log2size; hipe_mfa_info_table.log2size = log2size; hipe_mfa_info_table.mask = size - 1; hipe_mfa_info_table.used = 0; hipe_mfa_info_table.bucket = hipe_mfa_info_table_alloc_bucket(size);}static inline struct hipe_mfa_info *hipe_mfa_info_table_get(Eterm m, Eterm f, unsigned int arity){ unsigned long h; unsigned int i; struct hipe_mfa_info *p; h = HIPE_MFA_HASH(m, f, arity); i = h & hipe_mfa_info_table.mask; p = hipe_mfa_info_table.bucket[i]; for(; p; p = p->bucket.next) /* XXX: do we want to compare p->bucket.hvalue as well? */ if (p->m == m && p->f == f && p->a == arity) return p; return NULL;}#if 0 /* XXX: unused */void *hipe_mfa_find_na(Eterm m, Eterm f, unsigned int arity){ const struct hipe_mfa_info *p; p = hipe_mfa_info_table_get(m, f, arity); return p ? p->address : NULL;}#endifstatic struct hipe_mfa_info *hipe_mfa_info_table_put(Eterm m, Eterm f, unsigned int arity){ unsigned long h; unsigned int i; struct hipe_mfa_info *p; unsigned int size; h = HIPE_MFA_HASH(m, f, arity); i = h & hipe_mfa_info_table.mask; p = hipe_mfa_info_table.bucket[i]; for(; p; p = p->bucket.next) /* XXX: do we want to compare p->bucket.hvalue as well? */ if( p->m == m && p->f == f && p->a == arity )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -