303
382
hipe_constants_next = next;
304
383
constants_avail_words = CONSTANTS_BYTES / sizeof(Eterm);
306
if( nwords > constants_avail_words )
307
erl_exit(1, "out of constants pool memory\n");
385
if( nwords > constants_avail_words ) {
386
fprintf(stderr, "Native code constants pool depleted!\r\n");
387
/* Must terminate immediately. erl_exit() seems to
388
continue running some code which then SIGSEGVs. */
308
391
constants_avail_words -= nwords;
309
392
hipe_constants_next = next + nwords;
313
BIF_RETTYPE hipe_bifs_alloc_constant_1(BIF_ALIST_1)
318
if( is_not_small(BIF_ARG_1) )
319
BIF_ERROR(BIF_P, BADARG);
320
nwords = unsigned_val(BIF_ARG_1);
321
block = constants_alloc(nwords);
322
BIF_RET(address_to_term(block, BIF_P));
325
BIF_RETTYPE hipe_bifs_term_size_1(BIF_ALIST_1)
327
BIF_RET(make_small(size_object(BIF_ARG_1)));
330
BIF_RETTYPE hipe_bifs_copy_term_3(BIF_ALIST_3)
332
Eterm size, *hp, res;
334
hp = term_to_address(BIF_ARG_2);
335
if( !hp || is_not_small(BIF_ARG_3) || is_immed(BIF_ARG_1) )
336
BIF_ERROR(BIF_P, BADARG);
337
size = unsigned_val(BIF_ARG_3);
339
/* this only works as long as BIF_ARG_1 contains no binaries :-( */
340
res = copy_struct(BIF_ARG_1, size, &hp, NULL);
342
BIF_RET(address_to_term((void*)res, BIF_P));
396
BIF_RETTYPE hipe_bifs_constants_size_0(BIF_ALIST_0)
398
BIF_RET(make_small(hipe_constants_next - hipe_constants_start));
402
* Merging constant Erlang terms.
403
* Uses the constants pool and a hash table of all top-level
404
* terms merged so far. (Sub-terms are not merged.)
408
Eterm val; /* tagged pointer to mem[0] */
409
Eterm mem[1]; /* variable size */
412
static Hash const_term_table;
413
static ErlOffHeap const_term_table_off_heap;
415
static HashValue const_term_hash(void *tmpl)
417
return make_hash2((Eterm)tmpl);
420
static int const_term_cmp(void *tmpl, void *bucket)
422
return !eq((Eterm)tmpl, ((struct const_term*)bucket)->val);
425
static void *const_term_alloc(void *tmpl)
430
struct const_term *p;
433
ASSERT(is_not_immed(obj));
434
size = size_object(obj);
436
p = (struct const_term*)constants_alloc(size + (offsetof(struct const_term, mem)/sizeof(Eterm)));
438
/* I have absolutely no idea if having a private 'off_heap'
439
works or not. _Some_ off_heap object is required for
440
REFC_BINARY and FUN values, but _where_ it should be is
441
a complete mystery to me. */
443
p->val = copy_struct(obj, size, &hp, &const_term_table_off_heap);
448
static void init_const_term_table(void)
451
f.hash = (H_FUN) const_term_hash;
452
f.cmp = (HCMP_FUN) const_term_cmp;
453
f.alloc = (HALLOC_FUN) const_term_alloc;
454
f.free = (HFREE_FUN) NULL;
455
hash_init(ERTS_ALC_T_HIPE, &const_term_table, "const_term_table", 97, f);
458
BIF_RETTYPE hipe_bifs_merge_term_1(BIF_ALIST_1)
460
static int init_done = 0;
461
struct const_term *p;
465
if( is_not_immed(val) ) {
467
init_const_term_table();
470
p = (struct const_term*)hash_put(&const_term_table, (void*)val);
482
static int term_to_mfa(Eterm term, struct mfa *mfa)
487
if (is_not_tuple(term))
489
if (tuple_val(term)[0] != make_arityval(3))
491
mod = tuple_val(term)[1];
492
if (is_not_atom(mod))
495
fun = tuple_val(term)[2];
496
if (is_not_atom(fun))
499
a = tuple_val(term)[3];
502
ari = unsigned_val(a);
510
static void print_mfa(Eterm mod, Eterm fun, unsigned int ari)
512
erts_printf("%T:%T/%u", mod, fun, ari);
346
517
* Convert {M,F,A} to pointer to first insn after initial func_info.
348
Uint *hipe_bifs_find_pc_from_mfa(Eterm mfa)
519
static Uint *hipe_find_emu_address(Eterm mod, Eterm name, unsigned int arity)
361
if( tp[0] != make_arityval(3) )
365
if( !is_atom(mod) || !is_atom(name) || !is_small(tp[3]) )
367
arity = signed_val(tp[3]);
368
525
modp = erts_get_module(mod);
369
526
if( modp == NULL || (code_base = modp->code) == NULL )
458
650
hp[3] = make_small(funcinfo[2]);
459
651
BIF_RET(make_tuple(hp));
463
* Native-code stack descriptor hash table.
465
* This uses a specialised version of BEAM's hash table code:
466
* - hash table size is always a power of two
467
* permits replacing an expensive integer division operation
468
* with a cheap bitwise 'and' in the hash index calculation
469
* - lookups assume the key is in the table
470
* permits removing NULL checks
471
* - switched order of the hash bucket next and hvalue fields
472
* the hvalue field, which must always be checked, gets a zero
473
* structure offset, which is faster on some architectures;
474
* the next field is only referenced if hvalue didn't match
475
* These changes yield a much more efficient lookup operation.
477
struct hipe_sdesc_table hipe_sdesc_table;
479
static struct sdesc **alloc_bucket(unsigned int size)
481
unsigned long nbytes = size * sizeof(struct sdesc*);
482
struct sdesc **bucket = erts_alloc(ERTS_ALC_T_HIPE, nbytes);
483
sys_memzero(bucket, nbytes);
487
static void hipe_grow_sdesc_table(void)
489
unsigned int old_size, new_size, new_mask;
490
struct sdesc **old_bucket, **new_bucket;
493
old_size = 1 << hipe_sdesc_table.log2size;
494
hipe_sdesc_table.log2size += 1;
495
new_size = 1 << hipe_sdesc_table.log2size;
496
new_mask = new_size - 1;
497
hipe_sdesc_table.mask = new_mask;
498
old_bucket = hipe_sdesc_table.bucket;
499
new_bucket = alloc_bucket(new_size);
500
hipe_sdesc_table.bucket = new_bucket;
501
for(i = 0; i < old_size; ++i) {
502
struct sdesc *b = old_bucket[i];
504
struct sdesc *next = b->bucket.next;
505
unsigned int j = (b->bucket.hvalue >> HIPE_RA_LSR_COUNT) & new_mask;
506
b->bucket.next = new_bucket[j];
511
erts_free(ERTS_ALC_T_HIPE, old_bucket);
514
static struct sdesc *hipe_put_sdesc(struct sdesc *sdesc)
521
ra = sdesc->bucket.hvalue;
522
i = (ra >> HIPE_RA_LSR_COUNT) & hipe_sdesc_table.mask;
523
chain = hipe_sdesc_table.bucket[i];
525
for(; chain != NULL; chain = chain->bucket.next)
526
if( chain->bucket.hvalue == ra )
527
return chain; /* collision! (shouldn't happen) */
529
sdesc->bucket.next = hipe_sdesc_table.bucket[i];
530
hipe_sdesc_table.bucket[i] = sdesc;
531
hipe_sdesc_table.used += 1;
532
size = 1 << hipe_sdesc_table.log2size;
533
if( hipe_sdesc_table.used > (4*size)/5 ) /* rehash at 80% */
534
hipe_grow_sdesc_table();
538
void hipe_init_sdesc_table(struct sdesc *sdesc)
540
unsigned int log2size, size;
543
size = 1 << log2size;
544
hipe_sdesc_table.log2size = log2size;
545
hipe_sdesc_table.mask = size - 1;
546
hipe_sdesc_table.used = 0;
547
hipe_sdesc_table.bucket = alloc_bucket(size);
549
hipe_put_sdesc(sdesc);
552
/* XXX: remove later when sparc is more debugged
554
const struct sdesc *hipe_find_sdesc(unsigned long ra)
556
unsigned int i = (ra >> HIPE_RA_LSR_COUNT) & hipe_sdesc_table.mask;
557
const struct sdesc *sdesc = hipe_sdesc_table.bucket[i];
558
for(; sdesc; sdesc = sdesc->bucket.next)
559
if( sdesc->bucket.hvalue == ra )
561
fprintf(stderr, "%s: ra %#lx has no sdesc\r\n", __FUNCTION__, ra);
567
* XXX: x86 and SPARC currently use the same stack descriptor
568
* representation. If different representations are needed in
569
* the future, this code has to be made target dependent.
571
static struct sdesc *decode_sdesc(Eterm arg)
575
unsigned int fsize, arity, nlive, i, nslots, off;
576
unsigned int livebitswords, sdescwords;
580
if( is_not_tuple(arg) ||
581
(tuple_val(arg))[0] != make_arityval(5) ||
582
term_to_Uint((tuple_val(arg))[1], &ra) == 0 ||
583
term_to_Uint((tuple_val(arg))[2], &exnra) == 0 ||
584
is_not_small((tuple_val(arg))[3]) ||
585
(fsize = unsigned_val((tuple_val(arg))[3])) > 65535 ||
586
is_not_small((tuple_val(arg))[4]) ||
587
(arity = unsigned_val((tuple_val(arg))[4])) > 255 ||
588
is_not_tuple((tuple_val(arg))[5]) )
590
/* Get tuple with live slots */
591
live = tuple_val((tuple_val(arg))[5]) + 1;
592
/* Get number of live slots */
593
nlive = arityval(live[-1]);
594
/* Calculate size of frame = locals + ra + arguments */
595
nslots = fsize + 1 + arity;
596
/* Check that only valid slots are given. */
597
for(i = 0; i < nlive; ++i) {
598
if( is_not_small(live[i]) ||
599
(off = unsigned_val(live[i]), off >= nslots) ||
604
/* Calculate number of words for the live bitmap. */
605
livebitswords = (fsize + arity + 1 + 31) / 32;
606
/* Calculate number of words for the stack descriptor. */
607
sdescwords = 3 + livebitswords + (exnra ? 1 : 0);
608
p = erts_alloc(ERTS_ALC_T_HIPE, sdescwords*4);
609
/* If we have an exception handler use the
610
special sdesc_with_exnra structure. */
612
struct sdesc_with_exnra *sdesc_we = p;
613
sdesc_we->exnra = exnra;
614
sdesc = &(sdesc_we->sdesc);
618
/* Initialise head of sdesc. */
619
sdesc->bucket.next = 0;
620
sdesc->bucket.hvalue = ra;
621
sdesc->summary = (fsize << 9) | (exnra ? (1<<8) : 0) | arity;
622
/* Clear all live-bits */
623
for(i = 0; i < livebitswords; ++i)
624
sdesc->livebits[i] = 0;
625
/* Set live-bits given by caller. */
626
for(i = 0; i < nlive; ++i) {
627
off = unsigned_val(live[i]);
628
sdesc->livebits[off / 32] |= (1 << (off & 31));
633
655
BIF_RETTYPE hipe_bifs_enter_sdesc_1(BIF_ALIST_1)
635
657
struct sdesc *sdesc;
637
sdesc = decode_sdesc(BIF_ARG_1);
659
sdesc = hipe_decode_sdesc(BIF_ARG_1);
639
661
fprintf(stderr, "%s: bad sdesc!\r\n", __FUNCTION__);
640
662
BIF_ERROR(BIF_P, BADARG);
762
* Hash table mapping primops to their addresses.
765
HashBucket bucket; /* bucket.hvalue == atom_val(name) */
772
static struct primop primops[] = {
773
#define PRIMOP_LIST(ATOM,ADDRESS) { {0,_unchecked_atom_val(ATOM)}, ADDRESS },
774
#include "hipe_primops.h"
778
static Hash primop_table;
780
static HashValue primop_hash(void *tmpl)
782
return ((struct primop*)tmpl)->bucket.hvalue; /* pre-initialised */
785
static int primop_cmp(void *tmpl, void *bucket)
787
return 0; /* hvalue matched so nothing further to do */
790
static void *primop_alloc(void *tmpl)
792
return tmpl; /* pre-allocated */
795
static void init_primop_table(void)
799
static int init_done = 0;
805
f.hash = (H_FUN) primop_hash;
806
f.cmp = (HCMP_FUN) primop_cmp;
807
f.alloc = (HALLOC_FUN) primop_alloc;
810
hash_init(ERTS_ALC_T_HIPE, &primop_table, "primop_table", 50, f);
812
for(i = 0; i < sizeof(primops)/sizeof(primops[0]); ++i)
813
hash_put(&primop_table, &primops[i]);
816
static struct primop *primop_table_get(Eterm name)
821
tmpl.bucket.hvalue = atom_val(name);
822
return hash_get(&primop_table, &tmpl);
826
static struct primop *primop_table_put(Eterm name)
831
tmpl.bucket.hvalue = atom_val(name);
832
return hash_put(&primop_table, &tmpl);
835
void *hipe_primop_get_trampoline(Eterm name)
837
struct primop *primop = primop_table_get(name);
838
return primop ? primop->trampoline : NULL;
841
void hipe_primop_set_trampoline(Eterm name, void *trampoline)
843
struct primop *primop = primop_table_put(name);
844
primop->trampoline = trampoline;
740
849
* hipe_bifs_primop_address(Atom) -> address or false
742
851
BIF_RETTYPE hipe_bifs_primop_address_1(BIF_ALIST_1)
746
switch( BIF_ARG_1 ) {
747
#define check_bif(Name,Address) case Name: res = Address; break
748
check_bif(am_erl_fp_exception, (int*)&erl_fp_exception); /* ignore volatile */
749
check_bif(am_erts_mb, &erts_mb);
750
check_bif(am_erts_save_mb, &erts_save_mb);
752
check_bif(am_callemu, nbif_callemu);
753
check_bif(am_suspend_msg, nbif_suspend_msg);
754
check_bif(am_suspend_msg_timeout, nbif_suspend_msg_timeout);
755
check_bif(am_suspend_0, nbif_suspend_0);
757
check_bif(am_Plus, nbif_add_2);
758
check_bif(am_Minus, nbif_sub_2);
759
check_bif(am_Times, nbif_mul_2);
760
check_bif(am_Div, nbif_div_2);
761
check_bif(am_div, nbif_intdiv_2);
762
check_bif(am_rem, nbif_rem_2);
763
check_bif(am_bsl, nbif_bsl_2);
764
check_bif(am_bsr, nbif_bsr_2);
765
check_bif(am_band, nbif_band_2);
766
check_bif(am_bor, nbif_bor_2);
767
check_bif(am_bxor, nbif_bxor_2);
768
check_bif(am_bnot, nbif_bnot_1);
770
check_bif(am_gc_1, nbif_gc_1);
771
check_bif(am_get_msg, nbif_get_msg);
772
check_bif(am_select_msg, nbif_select_msg);
773
check_bif(am_mbox_empty, nbif_mbox_empty);
774
check_bif(am_next_msg, nbif_next_msg);
775
check_bif(am_set_timeout, nbif_set_timeout);
776
check_bif(am_clear_timeout, nbif_clear_timeout);
778
check_bif(am_bs_init, nbif_bs_init);
779
check_bif(am_bs_final, nbif_bs_final);
780
check_bif(am_bs_start_match, nbif_bs_start_match);
781
check_bif(am_bs_get_integer, nbif_bs_get_integer);
782
check_bif(am_bs_get_float, nbif_bs_get_float);
783
check_bif(am_bs_get_binary, nbif_bs_get_binary);
784
check_bif(am_bs_get_binary_all, nbif_bs_get_binary_all);
785
check_bif(am_bs_skip_bits, nbif_bs_skip_bits);
786
check_bif(am_bs_skip_bits_all, nbif_bs_skip_bits_all);
787
check_bif(am_bs_test_tail, nbif_bs_test_tail);
788
check_bif(am_bs_save, nbif_bs_save);
789
check_bif(am_bs_restore, nbif_bs_restore);
790
check_bif(am_bs_put_integer, nbif_bs_put_integer);
791
check_bif(am_bs_put_binary, nbif_bs_put_binary);
792
check_bif(am_bs_put_binary_all, nbif_bs_put_binary_all);
793
check_bif(am_bs_put_float, nbif_bs_put_float);
794
check_bif(am_bs_put_string, nbif_bs_put_string);
795
check_bif(am_bs_get_matchbuffer, nbif_bs_get_matchbuffer);
796
check_bif(am_bs_allocate, nbif_bs_allocate);
797
check_bif(am_bs_put_big_integer, nbif_bs_put_big_integer);
798
check_bif(am_bs_put_small_float, nbif_bs_put_small_float);
800
check_bif(am_cmp_2, nbif_cmp_2);
801
check_bif(am_op_exact_eqeq_2, nbif_eq_2);
803
check_bif(am_conv_big_to_float, nbif_conv_big_to_float);
806
check_bif(am_inc_stack_0args_0, nbif_inc_stack_0args);
807
check_bif(am_inc_stack_1args_0, nbif_inc_stack_1args);
808
check_bif(am_inc_stack_2args_0, nbif_inc_stack_2args);
809
check_bif(am_inc_stack_3args_0, nbif_inc_stack_3args);
810
check_bif(am_inc_stack_4args_0, nbif_inc_stack_4args);
811
check_bif(am_inc_stack_5args_0, nbif_inc_stack_5args);
812
check_bif(am_inc_stack_6args_0, nbif_inc_stack_6args);
813
check_bif(am_inc_stack_7args_0, nbif_inc_stack_7args);
814
check_bif(am_inc_stack_8args_0, nbif_inc_stack_8args);
815
check_bif(am_inc_stack_9args_0, nbif_inc_stack_9args);
816
check_bif(am_inc_stack_10args_0, nbif_inc_stack_10args);
817
check_bif(am_inc_stack_11args_0, nbif_inc_stack_11args);
818
check_bif(am_inc_stack_12args_0, nbif_inc_stack_12args);
819
check_bif(am_inc_stack_13args_0, nbif_inc_stack_13args);
820
check_bif(am_inc_stack_14args_0, nbif_inc_stack_14args);
821
check_bif(am_inc_stack_15args_0, nbif_inc_stack_15args);
822
check_bif(am_inc_stack_16args_0, nbif_inc_stack_16args);
825
check_bif(am_inc_stack_0, nbif_inc_stack_0);
826
check_bif(am_handle_fp_exception, nbif_handle_fp_exception);
832
BIF_RET(address_to_term(res, BIF_P));
853
const struct primop *primop;
855
if (is_not_atom(BIF_ARG_1))
857
primop = primop_table_get(BIF_ARG_1);
860
BIF_RET(address_to_term(primop->address, BIF_P));
863
#if 0 /* XXX: unused */
836
865
* hipe_bifs_gbif_address(F,A) -> address or false
1107
1060
char atom_buf[256];
1109
1062
atom_buf[0] = '\0';
1110
strncat(atom_buf, atom_tab(i)->name, atom_tab(i)->len);
1063
strncat(atom_buf, (char*)atom_tab(i)->name, atom_tab(i)->len);
1111
1064
printf("no fun entry for %s %ld:%ld\n", atom_buf, uniq, index);
1112
1065
BIF_ERROR(BIF_P, BADARG);
1114
1067
fe->native_address = native_address;
1068
if (erts_refc_dectest(&fe->refc, 0) == 0)
1069
erts_erase_fun_entry(fe);
1115
1070
BIF_RET(address_to_term((void *)fe, BIF_P));
1118
int hipe_patch_address(Uint *address, Eterm patchtype, Uint value)
1073
#if 0 /* XXX: unused */
1074
BIF_RETTYPE hipe_bifs_make_native_stub_2(BIF_ALIST_2)
1080
if( (beamAddress = term_to_address(BIF_ARG_1)) == 0 ||
1081
is_not_small(BIF_ARG_2) ||
1082
(beamArity = unsigned_val(BIF_ARG_2)) >= 256 )
1083
BIF_ERROR(BIF_P, BADARG);
1084
stubAddress = hipe_make_native_stub(beamAddress, beamArity);
1085
BIF_RET(address_to_term(stubAddress, BIF_P));
1090
* MFA info hash table:
1091
* - maps MFA to native code entry point
1092
* - the MFAs it calls (refers_to)
1093
* - the references to it (referred_from)
1094
* - maps MFA to most recent trampoline [if powerpc or arm]
1096
struct hipe_mfa_info {
1098
unsigned long hvalue;
1099
struct hipe_mfa_info *next;
1104
void *remote_address;
1105
void *local_address;
1108
struct hipe_mfa_info_list *refers_to;
1109
struct ref *referred_from;
1110
#if defined(__powerpc__) || defined(__ppc__) || defined(__powerpc64__) || defined(__arm__)
1116
unsigned int log2size;
1117
unsigned int mask; /* INV: mask == (1 << log2size)-1 */
1119
struct hipe_mfa_info **bucket;
1120
} hipe_mfa_info_table;
1122
#define HIPE_MFA_HASH(M,F,A) ((M) * (F) + (A))
1124
static struct hipe_mfa_info **hipe_mfa_info_table_alloc_bucket(unsigned int size)
1126
unsigned long nbytes = size * sizeof(struct hipe_mfa_info*);
1127
struct hipe_mfa_info **bucket = erts_alloc(ERTS_ALC_T_HIPE, nbytes);
1128
sys_memzero(bucket, nbytes);
1132
static void hipe_mfa_info_table_grow(void)
1134
unsigned int old_size, new_size, new_mask;
1135
struct hipe_mfa_info **old_bucket, **new_bucket;
1138
old_size = 1 << hipe_mfa_info_table.log2size;
1139
hipe_mfa_info_table.log2size += 1;
1140
new_size = 1 << hipe_mfa_info_table.log2size;
1141
new_mask = new_size - 1;
1142
hipe_mfa_info_table.mask = new_mask;
1143
old_bucket = hipe_mfa_info_table.bucket;
1144
new_bucket = hipe_mfa_info_table_alloc_bucket(new_size);
1145
hipe_mfa_info_table.bucket = new_bucket;
1146
for(i = 0; i < old_size; ++i) {
1147
struct hipe_mfa_info *b = old_bucket[i];
1148
while( b != NULL ) {
1149
struct hipe_mfa_info *next = b->bucket.next;
1150
unsigned int j = b->bucket.hvalue & new_mask;
1151
b->bucket.next = new_bucket[j];
1156
erts_free(ERTS_ALC_T_HIPE, old_bucket);
1159
static struct hipe_mfa_info *hipe_mfa_info_table_alloc(Eterm m, Eterm f, unsigned int arity)
1161
struct hipe_mfa_info *res;
1163
res = (struct hipe_mfa_info*)erts_alloc(ERTS_ALC_T_HIPE, sizeof(*res));
1167
res->remote_address = NULL;
1168
res->local_address = NULL;
1169
res->beam_code = NULL;
1170
res->orig_beam_op = 0;
1171
res->refers_to = NULL;
1172
res->referred_from = NULL;
1173
#if defined(__powerpc__) || defined(__ppc__) || defined(__powerpc64__) || defined(__arm__)
1174
res->trampoline = NULL;
1180
void hipe_mfa_info_table_init(void)
1182
unsigned int log2size, size;
1185
size = 1 << log2size;
1186
hipe_mfa_info_table.log2size = log2size;
1187
hipe_mfa_info_table.mask = size - 1;
1188
hipe_mfa_info_table.used = 0;
1189
hipe_mfa_info_table.bucket = hipe_mfa_info_table_alloc_bucket(size);
1192
static inline struct hipe_mfa_info *hipe_mfa_info_table_get(Eterm m, Eterm f, unsigned int arity)
1196
struct hipe_mfa_info *p;
1198
h = HIPE_MFA_HASH(m, f, arity);
1199
i = h & hipe_mfa_info_table.mask;
1200
p = hipe_mfa_info_table.bucket[i];
1201
for(; p; p = p->bucket.next)
1202
/* XXX: do we want to compare p->bucket.hvalue as well? */
1203
if (p->m == m && p->f == f && p->a == arity)
1208
#if 0 /* XXX: unused */
1209
void *hipe_mfa_find_na(Eterm m, Eterm f, unsigned int arity)
1211
const struct hipe_mfa_info *p;
1213
p = hipe_mfa_info_table_get(m, f, arity);
1214
return p ? p->address : NULL;
1218
static struct hipe_mfa_info *hipe_mfa_info_table_put(Eterm m, Eterm f, unsigned int arity)
1222
struct hipe_mfa_info *p;
1225
h = HIPE_MFA_HASH(m, f, arity);
1226
i = h & hipe_mfa_info_table.mask;
1227
p = hipe_mfa_info_table.bucket[i];
1228
for(; p; p = p->bucket.next)
1229
/* XXX: do we want to compare p->bucket.hvalue as well? */
1230
if( p->m == m && p->f == f && p->a == arity )
1232
p = hipe_mfa_info_table_alloc(m, f, arity);
1233
p->bucket.hvalue = h;
1234
p->bucket.next = hipe_mfa_info_table.bucket[i];
1235
hipe_mfa_info_table.bucket[i] = p;
1236
hipe_mfa_info_table.used += 1;
1237
size = 1 << hipe_mfa_info_table.log2size;
1238
if( hipe_mfa_info_table.used > (4*size/5) ) /* rehash at 80% */
1239
hipe_mfa_info_table_grow();
1243
static void hipe_mfa_set_na(Eterm m, Eterm f, unsigned int arity, void *address, int is_exported)
1245
struct hipe_mfa_info *p = hipe_mfa_info_table_put(m, f, arity);
1247
printf("%s: ", __FUNCTION__);
1248
print_mfa(m, f, arity);
1249
printf(": changing address from %p to %p\r\n", p->local_address, address);
1251
p->local_address = address;
1253
p->remote_address = address;
1256
#if defined(__powerpc__) || defined(__ppc__) || defined(__powerpc64__) || defined(__arm__)
1257
void *hipe_mfa_get_trampoline(Eterm m, Eterm f, unsigned int arity)
1259
struct hipe_mfa_info *p = hipe_mfa_info_table_put(m, f, arity);
1260
return p->trampoline;
1263
void hipe_mfa_set_trampoline(Eterm m, Eterm f, unsigned int arity, void *trampoline)
1265
struct hipe_mfa_info *p = hipe_mfa_info_table_put(m, f, arity);
1266
p->trampoline = trampoline;
1270
BIF_RETTYPE hipe_bifs_set_funinfo_native_address_3(BIF_ALIST_3)
1276
if (!term_to_mfa(BIF_ARG_1, &mfa))
1277
BIF_ERROR(BIF_P, BADARG);
1278
address = term_to_address(BIF_ARG_2);
1280
BIF_ERROR(BIF_P, BADARG);
1281
if (BIF_ARG_3 == am_true)
1283
else if (BIF_ARG_3 == am_false)
1286
BIF_ERROR(BIF_P, BADARG);
1287
hipe_mfa_set_na(mfa.mod, mfa.fun, mfa.ari, address, is_exported);
1291
BIF_RETTYPE hipe_bifs_invalidate_funinfo_native_addresses_1(BIF_ALIST_1)
1295
struct hipe_mfa_info *p;
1298
while (is_list(lst)) {
1299
if (!term_to_mfa(CAR(list_val(lst)), &mfa))
1300
BIF_ERROR(BIF_P, BADARG);
1301
lst = CDR(list_val(lst));
1302
p = hipe_mfa_info_table_get(mfa.mod, mfa.fun, mfa.ari);
1304
p->remote_address = NULL;
1305
p->local_address = NULL;
1308
printf("%s: ", __FUNCTION__);
1309
print_mfa(mfa.mod, mfa.fun, mfa.ari);
1310
printf(": removing call trap from BEAM pc %p (new op %#lx)\r\n",
1311
p->beam_code, p->orig_beam_op);
1313
p->beam_code[0] = p->orig_beam_op;
1314
p->beam_code = NULL;
1315
p->orig_beam_op = 0;
1318
printf("%s: ", __FUNCTION__);
1319
print_mfa(mfa.mod, mfa.fun, mfa.ari);
1320
printf(": no call trap to remove\r\n");
1325
if (is_not_nil(lst))
1326
BIF_ERROR(BIF_P, BADARG);
1330
void hipe_mfa_save_orig_beam_op(Eterm mod, Eterm fun, unsigned int ari, Eterm *pc)
1333
struct hipe_mfa_info *p;
1335
orig_beam_op = pc[0];
1336
if (orig_beam_op != BeamOpCode(op_hipe_trap_call_closure) &&
1337
orig_beam_op != BeamOpCode(op_hipe_trap_call)) {
1338
p = hipe_mfa_info_table_put(mod, fun, ari);
1340
printf("%s: ", __FUNCTION__);
1341
print_mfa(mod, fun, ari);
1342
printf(": saving orig op %#lx from BEAM pc %p\r\n", orig_beam_op, pc);
1345
p->orig_beam_op = orig_beam_op;
1348
printf("%s: ", __FUNCTION__);
1349
print_mfa(mod, fun, ari);
1350
printf(": orig op %#lx already saved\r\n", orig_beam_op);
1355
static void *hipe_make_stub(Eterm m, Eterm f, unsigned int arity, int is_remote)
1361
if( is_not_atom(m) || is_not_atom(f) || arity > 255 )
1364
BEAMAddress = hipe_get_emu_address(m, f, arity, is_remote);
1365
StubAddress = hipe_make_native_stub(BEAMAddress, arity);
1367
hipe_mfa_set_na(m, f, arity, StubAddress);
1372
static void *hipe_get_na_nofail(Eterm m, Eterm f, unsigned int a, int is_remote)
1374
struct hipe_mfa_info *p;
1377
p = hipe_mfa_info_table_get(m, f, a);
1379
/* find address, predicting for a runtime apply call */
1380
address = p->remote_address;
1382
address = p->local_address;
1386
/* bummer, install stub, checking if one already existed */
1387
address = p->remote_address;
1391
p = hipe_mfa_info_table_put(m, f, a);
1393
address = hipe_make_stub(m, f, a, is_remote);
1394
/* XXX: how to tell if a BEAM MFA is exported or not? */
1395
p->remote_address = address;
1399
/* used for apply/3 in hipe_mode_switch */
1400
void *hipe_get_remote_na(Eterm m, Eterm f, unsigned int a)
1402
if (is_not_atom(m) || is_not_atom(f) || a > 255)
1404
return hipe_get_na_nofail(m, f, a, 1);
1407
/* primop, but called like a BIF for error handling purposes */
1408
BIF_RETTYPE hipe_find_na_or_make_stub(BIF_ALIST_3)
1413
if( is_not_atom(BIF_ARG_1) || is_not_atom(BIF_ARG_2) )
1414
BIF_ERROR(BIF_P, BADARG);
1415
arity = unsigned_val(BIF_ARG_3); /* no error check */
1416
address = hipe_get_na_nofail(BIF_ARG_1, BIF_ARG_2, arity, 1);
1417
BIF_RET((Eterm)address); /* semi-Ok */
1420
BIF_RETTYPE hipe_bifs_find_na_or_make_stub_2(BIF_ALIST_2)
1426
if (!term_to_mfa(BIF_ARG_1, &mfa))
1427
BIF_ERROR(BIF_P, BADARG);
1428
if (BIF_ARG_2 == am_true)
1430
else if (BIF_ARG_2 == am_false)
1433
BIF_ERROR(BIF_P, BADARG);
1434
address = hipe_get_na_nofail(mfa.mod, mfa.fun, mfa.ari, is_remote);
1435
BIF_RET(address_to_term(address, BIF_P));
1438
/* primop, but called like a BIF for error handling purposes */
1439
BIF_RETTYPE hipe_nonclosure_address(BIF_ALIST_2)
1444
if (!is_boxed(BIF_ARG_1))
1446
hdr = *boxed_val(BIF_ARG_1);
1447
if (is_export_header(hdr)) {
1448
Export *ep = (Export*)(export_val(BIF_ARG_1)[1]);
1449
unsigned int actual_arity = ep->code[2];
1450
if (actual_arity != BIF_ARG_2)
1454
} else if (hdr == make_arityval(2)) {
1455
Eterm *tp = tuple_val(BIF_ARG_1);
1458
if (is_not_atom(m) || is_not_atom(f))
1460
if (!erts_find_export_entry(m, f, BIF_ARG_2))
1464
address = hipe_get_na_nofail(m, f, BIF_ARG_2, 1);
1465
BIF_RET((Eterm)address);
1468
BIF_P->current = NULL;
1469
BIF_P->fvalue = BIF_ARG_1;
1470
BIF_ERROR(BIF_P, EXC_BADFUN);
1474
* Patch Reference Handling.
1476
struct hipe_mfa_info_list {
1477
struct hipe_mfa_info *mfa;
1478
struct hipe_mfa_info_list *next;
1482
struct hipe_mfa_info *caller_mfa;
1488
#define REF_FLAG_IS_LOAD_MFA 1 /* bit 0: 0 == call, 1 == load_mfa */
1489
#define REF_FLAG_IS_REMOTE 2 /* bit 1: 0 == local, 1 == remote */
1490
#define REF_FLAG_PENDING_REDIRECT 4 /* bit 2: 1 == pending redirect */
1491
#define REF_FLAG_PENDING_REMOVE 8 /* bit 3: 1 == pending remove */
1493
/* add_ref(CalleeMFA, {CallerMFA,Address,'call'|'load_mfa',Trampoline,'remote'|'local'})
1495
BIF_RETTYPE hipe_bifs_add_ref_2(BIF_ALIST_2)
1503
struct hipe_mfa_info *callee_mfa;
1504
struct hipe_mfa_info *caller_mfa;
1505
struct hipe_mfa_info_list *refers_to;
1508
if (!term_to_mfa(BIF_ARG_1, &callee))
1510
if (is_not_tuple(BIF_ARG_2))
1512
tuple = tuple_val(BIF_ARG_2);
1513
if (tuple[0] != make_arityval(5))
1515
if (!term_to_mfa(tuple[1], &caller))
1517
address = term_to_address(tuple[2]);
1525
flags = REF_FLAG_IS_LOAD_MFA;
1530
if (is_nil(tuple[4]))
1533
trampoline = term_to_address(tuple[4]);
1541
flags |= REF_FLAG_IS_REMOTE;
1546
callee_mfa = hipe_mfa_info_table_put(callee.mod, callee.fun, callee.ari);
1547
caller_mfa = hipe_mfa_info_table_put(caller.mod, caller.fun, caller.ari);
1549
refers_to = erts_alloc(ERTS_ALC_T_HIPE, sizeof(*refers_to));
1550
refers_to->mfa = callee_mfa;
1551
refers_to->next = caller_mfa->refers_to;
1552
caller_mfa->refers_to = refers_to;
1554
ref = erts_alloc(ERTS_ALC_T_HIPE, sizeof(*ref));
1555
ref->caller_mfa = caller_mfa;
1556
ref->address = address;
1557
ref->trampoline = trampoline;
1559
ref->next = callee_mfa->referred_from;
1560
callee_mfa->referred_from = ref;
1565
BIF_ERROR(BIF_P, BADARG);
1568
/* Given a CalleeMFA, mark each ref to it as pending-redirect.
1569
* This ensures that remove_refs_from() won't remove them: any
1570
* removal is instead done at the end of redirect_referred_from().
1572
BIF_RETTYPE hipe_bifs_mark_referred_from_1(BIF_ALIST_1) /* get_refs_from */
1575
const struct hipe_mfa_info *p;
1578
if (!term_to_mfa(BIF_ARG_1, &mfa))
1579
BIF_ERROR(BIF_P, BADARG);
1580
p = hipe_mfa_info_table_get(mfa.mod, mfa.fun, mfa.ari);
1582
for(ref = p->referred_from; ref != NULL; ref = ref->next)
1583
ref->flags |= REF_FLAG_PENDING_REDIRECT;
1587
BIF_RETTYPE hipe_bifs_remove_refs_from_1(BIF_ALIST_1)
1590
struct hipe_mfa_info *caller_mfa, *callee_mfa;
1591
struct hipe_mfa_info_list *refers_to, *tmp_refers_to;
1592
struct ref **prev, *ref;
1594
if (!term_to_mfa(BIF_ARG_1, &mfa))
1595
BIF_ERROR(BIF_P, BADARG);
1596
caller_mfa = hipe_mfa_info_table_get(mfa.mod, mfa.fun, mfa.ari);
1598
refers_to = caller_mfa->refers_to;
1600
callee_mfa = refers_to->mfa;
1601
prev = &callee_mfa->referred_from;
1604
if (ref->caller_mfa == caller_mfa) {
1605
if (ref->flags & REF_FLAG_PENDING_REDIRECT) {
1606
ref->flags |= REF_FLAG_PENDING_REMOVE;
1610
struct ref *tmp = ref;
1613
erts_free(ERTS_ALC_T_HIPE, tmp);
1620
tmp_refers_to = refers_to;
1621
refers_to = refers_to->next;
1622
erts_free(ERTS_ALC_T_HIPE, tmp_refers_to);
1624
caller_mfa->refers_to = NULL;
1629
/* redirect_referred_from(CalleeMFA)
1630
* Redirect all pending-redirect refs in CalleeMFA's referred_from.
1631
* Then remove any pending-redirect && pending-remove refs from CalleeMFA's referred_from.
1633
BIF_RETTYPE hipe_bifs_redirect_referred_from_1(BIF_ALIST_1)
1636
struct hipe_mfa_info *p;
1637
struct ref **prev, *ref;
1641
if (!term_to_mfa(BIF_ARG_1, &mfa))
1642
BIF_ERROR(BIF_P, BADARG);
1643
p = hipe_mfa_info_table_get(mfa.mod, mfa.fun, mfa.ari);
1645
prev = &p->referred_from;
1648
if (ref->flags & REF_FLAG_PENDING_REDIRECT) {
1649
is_remote = ref->flags & REF_FLAG_IS_REMOTE;
1650
new_address = hipe_get_na_nofail(p->m, p->f, p->a, is_remote);
1651
if (ref->flags & REF_FLAG_IS_LOAD_MFA)
1652
res = hipe_patch_insn(ref->address, (Uint)new_address, am_load_mfa);
1654
res = hipe_patch_call(ref->address, new_address, ref->trampoline);
1656
fprintf(stderr, "%s: patch failed\r\n", __FUNCTION__);
1657
ref->flags &= ~REF_FLAG_PENDING_REDIRECT;
1658
if (ref->flags & REF_FLAG_PENDING_REMOVE) {
1659
struct ref *tmp = ref;
1662
erts_free(ERTS_ALC_T_HIPE, tmp);
1676
BIF_RETTYPE hipe_bifs_check_crc_1(BIF_ALIST_1)
1680
if (!term_to_Uint(BIF_ARG_1, &crc))
1681
BIF_ERROR(BIF_P, BADARG);
1682
if (crc == HIPE_SYSTEM_CRC)
1687
BIF_RETTYPE hipe_bifs_system_crc_1(BIF_ALIST_1)
1691
if (!term_to_Uint(BIF_ARG_1, &crc))
1692
BIF_ERROR(BIF_P, BADARG);
1693
crc ^= (HIPE_SYSTEM_CRC ^ HIPE_LITERALS_CRC);
1694
BIF_RET(Uint_to_term(crc, BIF_P));
1697
BIF_RETTYPE hipe_bifs_get_rts_param_1(BIF_ALIST_1)
1699
unsigned int is_defined;
1700
unsigned long value;
1702
if( is_not_small(BIF_ARG_1) )
1703
BIF_ERROR(BIF_P, BADARG);
1706
switch( unsigned_val(BIF_ARG_1) ) {
1709
BIF_ERROR(BIF_P, BADARG);
1713
BIF_RET(Uint_to_term(value, BIF_P));
1716
void hipe_patch_address(Uint *address, Eterm patchtype, Uint value)
1120
1718
switch( patchtype ) {
1121
#if defined(__i386__)
1123
{ /* address points to a disp32 or imm32 operand */
1128
#if defined(__sparc__)
1130
{ /* address points to a SETHI insn */
1131
unsigned int high22 = value >> 10;
1132
unsigned int sethi_insn = *address;
1133
*address = (sethi_insn & 0xFFC00000) | high22;
1134
/* Flush the I-cache. */
1135
asm volatile("flush %0"
1142
{ /* address points to an OR reg,imm,reg insn */
1143
unsigned int low10 = value & 0x3FF;
1144
unsigned int or_insn = *address;
1145
*address = (or_insn & 0xFFFFE000) | low10;
1146
/* Flush the I-cache. */
1147
asm volatile("flush %0"
1720
hipe_patch_load_fe(address, value);
1156
fprintf(stderr, "hipe_patch_address: unknown patchtype %#lx\r\n",
1163
BIF_RETTYPE hipe_bifs_check_crc_1(BIF_ALIST_1)
1167
term_to_Uint(BIF_ARG_1, &crc);
1169
BIF_ERROR(BIF_P, BADARG);
1170
if( crc == HIPE_SYSTEM_CRC )
1723
fprintf(stderr, "%s: unknown patchtype %#lx\r\n",
1724
__FUNCTION__, patchtype);
1730
HashBucket bucket; /* bucket.hvalue == atom_val(the module name) */
1731
unsigned int code_size;
1734
static Hash modinfo_table;
1736
static HashValue modinfo_hash(void *tmpl)
1738
Eterm mod = (Eterm)tmpl;
1739
return atom_val(mod);
1742
static int modinfo_cmp(void *tmpl, void *bucket)
1744
/* bucket->hvalue == modinfo_hash(tmpl), so just return 0 (match) */
1748
static void *modinfo_alloc(void *tmpl)
1752
p = (struct modinfo*)erts_alloc(ERTS_ALC_T_HIPE, sizeof(*p));
1757
static void init_modinfo_table(void)
1760
static int init_done = 0;
1765
f.hash = (H_FUN) modinfo_hash;
1766
f.cmp = (HCMP_FUN) modinfo_cmp;
1767
f.alloc = (HALLOC_FUN) modinfo_alloc;
1768
f.free = (HFREE_FUN) NULL;
1769
hash_init(ERTS_ALC_T_HIPE, &modinfo_table, "modinfo_table", 11, f);
1772
BIF_RETTYPE hipe_bifs_update_code_size_3(BIF_ALIST_3)
1777
init_modinfo_table();
1779
if (is_not_atom(BIF_ARG_1) ||
1780
is_not_small(BIF_ARG_3) ||
1781
(code_size = signed_val(BIF_ARG_3)) < 0)
1782
BIF_ERROR(BIF_P, BADARG);
1784
p = (struct modinfo*)hash_put(&modinfo_table, (void*)BIF_ARG_1);
1786
if (is_nil(BIF_ARG_2)) /* some MFAs, not whole module */
1787
p->code_size += code_size;
1788
else /* whole module */
1789
p->code_size = code_size;
1793
BIF_RETTYPE hipe_bifs_code_size_1(BIF_ALIST_1)
1796
unsigned int code_size;
1798
init_modinfo_table();
1800
if (is_not_atom(BIF_ARG_1))
1801
BIF_ERROR(BIF_P, BADARG);
1803
p = (struct modinfo*)hash_get(&modinfo_table, (void*)BIF_ARG_1);
1805
code_size = p ? p->code_size : 0;
1806
BIF_RET(make_small(code_size));
1809
BIF_RETTYPE hipe_bifs_patch_insn_3(BIF_ALIST_3)
1811
Uint *address, value;
1813
address = term_to_address(BIF_ARG_1);
1815
BIF_ERROR(BIF_P, BADARG);
1816
if (!term_to_Uint(BIF_ARG_2, &value))
1817
BIF_ERROR(BIF_P, BADARG);
1818
if (hipe_patch_insn(address, value, BIF_ARG_3))
1819
BIF_ERROR(BIF_P, BADARG);
1823
BIF_RETTYPE hipe_bifs_patch_call_3(BIF_ALIST_3)
1825
Uint *callAddress, *destAddress, *trampAddress;
1827
callAddress = term_to_address(BIF_ARG_1);
1829
BIF_ERROR(BIF_P, BADARG);
1830
destAddress = term_to_address(BIF_ARG_2);
1832
BIF_ERROR(BIF_P, BADARG);
1833
if (is_nil(BIF_ARG_3))
1834
trampAddress = NULL;
1836
trampAddress = term_to_address(BIF_ARG_3);
1838
BIF_ERROR(BIF_P, BADARG);
1840
if (hipe_patch_call(callAddress, destAddress, trampAddress))
1841
BIF_ERROR(BIF_P, BADARG);