mirror of
https://github.com/urbit/shrub.git
synced 2024-12-21 09:51:36 +03:00
Merge pull request #3612 from urbit/jb/slab
u3: replaces atom slab-allocation api for efficiency
This commit is contained in:
commit
6bc52c0591
@ -52,11 +52,11 @@ _jam_bench(void)
|
||||
gettimeofday(&b4, 0);
|
||||
|
||||
{
|
||||
c3_w* wor_w, bit_w;
|
||||
u3i_slab sab_u;
|
||||
|
||||
for ( i_w = 0; i_w < max_w; i_w++ ) {
|
||||
wor_w = u3s_jam_fib(wit, &bit_w);
|
||||
u3a_wfree(wor_w);
|
||||
u3s_jam_fib(&sab_u, wit);
|
||||
u3i_slab_free(&sab_u);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -414,6 +414,11 @@
|
||||
void
|
||||
u3a_wfree(void* lag_v);
|
||||
|
||||
/* u3a_wtrim(): trim storage.
|
||||
*/
|
||||
void
|
||||
u3a_wtrim(void* tox_v, c3_w old_w, c3_w len_w);
|
||||
|
||||
/* u3a_wealloc(): word realloc.
|
||||
*/
|
||||
void*
|
||||
@ -643,33 +648,6 @@
|
||||
void
|
||||
u3a_deadbeef(void);
|
||||
|
||||
/* Atoms from proto-atoms.
|
||||
*/
|
||||
/* u3a_slab(): create a length-bounded proto-atom.
|
||||
*/
|
||||
c3_w*
|
||||
u3a_slab(c3_w len_w);
|
||||
|
||||
/* u3a_slaq(): u3a_slab() with a defined blocksize.
|
||||
*/
|
||||
c3_w*
|
||||
u3a_slaq(c3_g met_g, c3_w len_w);
|
||||
|
||||
/* u3a_malt(): measure and finish a proto-atom.
|
||||
*/
|
||||
u3_noun
|
||||
u3a_malt(c3_w* sal_w);
|
||||
|
||||
/* u3a_moot(): finish a pre-measured proto-atom; dangerous.
|
||||
*/
|
||||
u3_noun
|
||||
u3a_moot(c3_w* sal_w);
|
||||
|
||||
/* u3a_mint(): finish a measured proto-atom.
|
||||
*/
|
||||
u3_noun
|
||||
u3a_mint(c3_w* sal_w, c3_w len_w);
|
||||
|
||||
/* u3a_walk_fore(): preorder traversal, visits ever limb of a noun.
|
||||
**
|
||||
** cells are visited *before* their heads and tails
|
||||
|
@ -2,17 +2,91 @@
|
||||
**
|
||||
** This file is in the public domain.
|
||||
*/
|
||||
|
||||
/** Structures.
|
||||
**/
|
||||
/* u3i_slab: atom builder.
|
||||
*/
|
||||
typedef struct _u3i_slab {
|
||||
struct { // internals
|
||||
u3a_atom* _vat_u; // heap atom (nullable)
|
||||
c3_w _sat_w; // static storage
|
||||
} _; //
|
||||
union { //
|
||||
c3_y* buf_y; // bytes
|
||||
c3_w* buf_w; // words
|
||||
}; //
|
||||
c3_w len_w; // word length
|
||||
} u3i_slab;
|
||||
|
||||
/* staged atom-building api
|
||||
*/
|
||||
/* u3i_slab_init(): configure bloq-length slab, zero-initialize.
|
||||
*/
|
||||
void
|
||||
u3i_slab_init(u3i_slab* sab_u, c3_g met_g, c3_d len_d);
|
||||
|
||||
/* u3i_slab_bare(): configure bloq-length slab, uninitialized.
|
||||
*/
|
||||
void
|
||||
u3i_slab_bare(u3i_slab* sab_u, c3_g met_g, c3_d len_d);
|
||||
|
||||
/* u3i_slab_from(): configure bloq-length slab, initialize with [a].
|
||||
*/
|
||||
void
|
||||
u3i_slab_from(u3i_slab* sab_u, u3_atom a, c3_g met_g, c3_d len_d);
|
||||
|
||||
/* u3i_slab_grow(): resize slab, zero-initializing new space.
|
||||
*/
|
||||
void
|
||||
u3i_slab_grow(u3i_slab* sab_u, c3_g met_g, c3_d len_d);
|
||||
|
||||
/* u3i_slab_free(): dispose memory backing slab.
|
||||
*/
|
||||
void
|
||||
u3i_slab_free(u3i_slab* sab_u);
|
||||
|
||||
/* u3i_slab_mint(): produce atom from slab, trimming.
|
||||
*/
|
||||
u3_atom
|
||||
u3i_slab_mint(u3i_slab* sab_u);
|
||||
|
||||
/* u3i_slab_moot(): produce atom from slab, no trimming.
|
||||
*/
|
||||
u3_atom
|
||||
u3i_slab_moot(u3i_slab* sab_u);
|
||||
|
||||
/* u3i_slab_mint_bytes(): produce atom from byte-slab, trimming.
|
||||
** XX assumes little-endian, implement swap to support big-endian
|
||||
*/
|
||||
# define u3i_slab_mint_bytes u3i_slab_mint
|
||||
|
||||
/* u3i_slab_moot_bytes(): produce atom from byte-slab, no trimming.
|
||||
** XX assumes little-endian, implement swap to support big-endian
|
||||
*/
|
||||
# define u3i_slab_moot_bytes u3i_slab_moot
|
||||
|
||||
/* General constructors.
|
||||
*/
|
||||
/* u3i_word(): construct u3_atom from c3_w.
|
||||
*/
|
||||
u3_atom
|
||||
u3i_word(c3_w dat_w);
|
||||
|
||||
/* u3i_chub(): construct u3_atom from c3_d.
|
||||
*/
|
||||
u3_atom
|
||||
u3i_chub(c3_d dat_d);
|
||||
|
||||
/* u3i_bytes(): Copy [a] bytes from [b] to an LSB first atom.
|
||||
*/
|
||||
u3_noun
|
||||
u3_atom
|
||||
u3i_bytes(c3_w a_w,
|
||||
const c3_y* b_y);
|
||||
|
||||
/* u3i_words(): Copy [a] words from [b] into an atom.
|
||||
*/
|
||||
u3_noun
|
||||
u3_atom
|
||||
u3i_words(c3_w a_w,
|
||||
const c3_w* b_w);
|
||||
|
||||
@ -24,12 +98,12 @@
|
||||
|
||||
/* u3i_mp(): Copy the GMP integer [a] into an atom, and clear it.
|
||||
*/
|
||||
u3_noun
|
||||
u3_atom
|
||||
u3i_mp(mpz_t a_mp);
|
||||
|
||||
/* u3i_vint(): increment [a].
|
||||
*/
|
||||
u3_noun
|
||||
u3_atom
|
||||
u3i_vint(u3_noun a);
|
||||
|
||||
/* u3i_cell(): Produce the cell `[a b]`.
|
||||
|
@ -15,8 +15,8 @@
|
||||
** returns atom-suitable words, and *bit_w will have
|
||||
** the length (in bits). return should be freed with u3a_wfree().
|
||||
*/
|
||||
c3_w*
|
||||
u3s_jam_fib(u3_noun a, c3_w* bit_w);
|
||||
c3_w
|
||||
u3s_jam_fib(u3i_slab* sab_u, u3_noun a);
|
||||
|
||||
/* u3s_jam_xeno(): jam with off-loom buffer (re-)allocation.
|
||||
*/
|
||||
|
@ -14,9 +14,9 @@
|
||||
return u3m_bail(c3__fail);
|
||||
}
|
||||
else {
|
||||
c3_g a_g = a;
|
||||
c3_w tot_w = 0;
|
||||
c3_w* sal_w;
|
||||
c3_g a_g = a;
|
||||
c3_w tot_w = 0;
|
||||
u3i_slab sab_u;
|
||||
|
||||
/* Measure and validate the slab required.
|
||||
*/
|
||||
@ -41,12 +41,12 @@
|
||||
tot_w += pi_cab;
|
||||
cab = u3t(cab);
|
||||
}
|
||||
|
||||
if ( 0 == tot_w ) {
|
||||
return 0;
|
||||
}
|
||||
if ( 0 == (sal_w = u3a_slaq(a_g, tot_w)) ) {
|
||||
return u3m_bail(c3__fail);
|
||||
}
|
||||
|
||||
u3i_slab_init(&sab_u, a_g, tot_w);
|
||||
}
|
||||
|
||||
/* Chop the list atoms in.
|
||||
@ -60,12 +60,13 @@
|
||||
u3_atom pi_cab = u3h(i_cab);
|
||||
u3_atom qi_cab = u3t(i_cab);
|
||||
|
||||
u3r_chop(a_g, 0, pi_cab, pos_w, sal_w, qi_cab);
|
||||
u3r_chop(a_g, 0, pi_cab, pos_w, sab_u.buf_w, qi_cab);
|
||||
pos_w += pi_cab;
|
||||
cab = u3t(cab);
|
||||
}
|
||||
}
|
||||
return u3a_malt(sal_w);
|
||||
|
||||
return u3i_slab_mint(&sab_u);
|
||||
}
|
||||
}
|
||||
u3_noun
|
||||
|
@ -22,18 +22,14 @@
|
||||
|
||||
if ( 0 == all_w ) {
|
||||
return 0;
|
||||
} else {
|
||||
c3_w* sal_w = u3a_slaq(a_g, all_w);
|
||||
}
|
||||
else {
|
||||
u3i_slab sab_u;
|
||||
u3i_slab_from(&sab_u, b, a_g, all_w);
|
||||
|
||||
if ( 0 == sal_w ) {
|
||||
return u3m_bail(c3__fail);
|
||||
}
|
||||
else {
|
||||
u3r_chop(a_g, 0, lew_w, 0, sal_w, b);
|
||||
u3r_chop(a_g, 0, ler_w, lew_w, sal_w, c);
|
||||
}
|
||||
// return u3a_moot(sal_w);
|
||||
return u3a_malt(sal_w);
|
||||
u3r_chop(a_g, 0, ler_w, lew_w, sab_u.buf_w, c);
|
||||
|
||||
return u3i_slab_mint(&sab_u);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,24 +15,18 @@
|
||||
|
||||
if ( (lna_w == 0) && (lnb_w == 0) ) {
|
||||
return 0;
|
||||
} else {
|
||||
c3_w len_w = c3_max(lna_w, lnb_w);
|
||||
c3_w* sal_w = u3a_slab(len_w);
|
||||
}
|
||||
else {
|
||||
c3_w len_w = c3_max(lna_w, lnb_w);
|
||||
c3_w i_w;
|
||||
u3i_slab sab_u;
|
||||
u3i_slab_from(&sab_u, a, 5, len_w);
|
||||
|
||||
if ( 0 == sal_w ) {
|
||||
return u3m_bail(c3__fail);
|
||||
for ( i_w = 0; i_w < lnb_w; i_w++ ) {
|
||||
sab_u.buf_w[i_w] |= u3r_word(i_w, b);
|
||||
}
|
||||
else {
|
||||
c3_w i_w;
|
||||
|
||||
u3r_chop(5, 0, lna_w, 0, sal_w, a);
|
||||
|
||||
for ( i_w = 0; i_w < lnb_w; i_w++ ) {
|
||||
sal_w[i_w] |= u3r_word(i_w, b);
|
||||
}
|
||||
// return u3a_moot(sal_w);
|
||||
return u3a_malt(sal_w);
|
||||
}
|
||||
return u3i_slab_mint(&sab_u);
|
||||
}
|
||||
}
|
||||
u3_noun
|
||||
|
@ -38,14 +38,12 @@
|
||||
return u3k(d);
|
||||
}
|
||||
else {
|
||||
c3_w* sal_w = u3a_slaq(a_g, c_w);
|
||||
u3i_slab sab_u;
|
||||
u3i_slab_init(&sab_u, a_g, c_w);
|
||||
|
||||
if ( 0 == sal_w ) {
|
||||
return u3m_bail(c3__fail);
|
||||
}
|
||||
u3r_chop(a_g, b_w, c_w, 0, sal_w, d);
|
||||
u3r_chop(a_g, b_w, c_w, 0, sab_u.buf_w, d);
|
||||
|
||||
return u3a_malt(sal_w);
|
||||
return u3i_slab_mint(&sab_u);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,23 +15,18 @@
|
||||
|
||||
if ( (lna_w == 0) && (lnb_w == 0) ) {
|
||||
return 0;
|
||||
} else {
|
||||
c3_w len_w = c3_max(lna_w, lnb_w);
|
||||
c3_w* sal_w = u3a_slab(len_w);
|
||||
}
|
||||
else {
|
||||
c3_w len_w = c3_max(lna_w, lnb_w);
|
||||
c3_w i_w;
|
||||
u3i_slab sab_u;
|
||||
u3i_slab_from(&sab_u, a, 5, len_w);
|
||||
|
||||
if ( 0 == sal_w ) {
|
||||
return u3m_bail(c3__fail);
|
||||
for ( i_w = 0; i_w < len_w; i_w++ ) {
|
||||
sab_u.buf_w[i_w] &= u3r_word(i_w, b);
|
||||
}
|
||||
else {
|
||||
c3_w i_w;
|
||||
|
||||
u3r_chop(5, 0, lna_w, 0, sal_w, a);
|
||||
|
||||
for ( i_w = 0; i_w < len_w; i_w++ ) {
|
||||
sal_w[i_w] &= (i_w >= lnb_w) ? 0 : u3r_word(i_w, b);
|
||||
}
|
||||
return u3a_malt(sal_w);
|
||||
}
|
||||
return u3i_slab_mint(&sab_u);
|
||||
}
|
||||
}
|
||||
u3_noun
|
||||
|
@ -29,14 +29,12 @@
|
||||
return u3k(c);
|
||||
}
|
||||
else {
|
||||
c3_w* sal_w = u3a_slaq(a_g, b_w);
|
||||
u3i_slab sab_u;
|
||||
u3i_slab_init(&sab_u, a_g, b_w);
|
||||
|
||||
if ( 0 == sal_w ) {
|
||||
return u3m_bail(c3__fail);
|
||||
}
|
||||
u3r_chop(a_g, 0, b_w, 0, sal_w, c);
|
||||
u3r_chop(a_g, 0, b_w, 0, sab_u.buf_w, c);
|
||||
|
||||
return u3a_malt(sal_w);
|
||||
return u3i_slab_mint(&sab_u);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,15 +29,12 @@
|
||||
return u3m_bail(c3__exit);
|
||||
}
|
||||
else {
|
||||
c3_w* sal_w = u3a_slaq(a_g, (b_w + len_w));
|
||||
u3i_slab sab_u;
|
||||
u3i_slab_init(&sab_u, a_g, (b_w + len_w));
|
||||
|
||||
if ( 0 == sal_w ) {
|
||||
return u3m_bail(c3__fail);
|
||||
}
|
||||
u3r_chop(a_g, 0, len_w, b_w, sal_w, c);
|
||||
u3r_chop(a_g, 0, len_w, b_w, sab_u.buf_w, c);
|
||||
|
||||
// return u3a_moot(sal_w);
|
||||
return u3a_malt(sal_w);
|
||||
return u3i_slab_mint(&sab_u);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,23 +15,20 @@
|
||||
|
||||
if ( (lna_w == 0) && (lnb_w == 0) ) {
|
||||
return 0;
|
||||
} else {
|
||||
c3_w len_w = c3_max(lna_w, lnb_w);
|
||||
c3_w* sal_w = u3a_slab(len_w);
|
||||
}
|
||||
else {
|
||||
c3_w len_w = c3_max(lna_w, lnb_w);
|
||||
c3_w i_w;
|
||||
u3i_slab sab_u;
|
||||
u3i_slab_from(&sab_u, a, 5, len_w);
|
||||
|
||||
if ( 0 == sal_w ) {
|
||||
return u3m_bail(c3__fail);
|
||||
// XX use u3r_chop for XOR?
|
||||
//
|
||||
for ( i_w = 0; i_w < lnb_w; i_w++ ) {
|
||||
sab_u.buf_w[i_w] ^= u3r_word(i_w, b);
|
||||
}
|
||||
else {
|
||||
c3_w i_w;
|
||||
|
||||
u3r_chop(5, 0, lna_w, 0, sal_w, a);
|
||||
|
||||
for ( i_w = 0; i_w < lnb_w; i_w++ ) {
|
||||
sal_w[i_w] ^= u3r_word(i_w, b);
|
||||
}
|
||||
return u3a_malt(sal_w);
|
||||
}
|
||||
return u3i_slab_mint(&sab_u);
|
||||
}
|
||||
}
|
||||
u3_noun
|
||||
|
@ -14,9 +14,9 @@
|
||||
return u3m_bail(c3__exit);
|
||||
}
|
||||
else {
|
||||
c3_g a_g = a;
|
||||
c3_w tot_w = 0;
|
||||
c3_w* sal_w;
|
||||
c3_g a_g = a;
|
||||
c3_w tot_w = 0;
|
||||
u3i_slab sab_u;
|
||||
|
||||
/* Measure and validate the slab required.
|
||||
*/
|
||||
@ -42,31 +42,31 @@
|
||||
tot_w += len_w;
|
||||
cab = u3t(cab);
|
||||
}
|
||||
|
||||
if ( 0 == tot_w ) {
|
||||
return 0;
|
||||
}
|
||||
if ( 0 == (sal_w = u3a_slaq(a_g, tot_w)) ) {
|
||||
return u3m_bail(c3__fail);
|
||||
}
|
||||
|
||||
u3i_slab_init(&sab_u, a_g, tot_w);
|
||||
}
|
||||
|
||||
/* Chop the list atoms in.
|
||||
*/
|
||||
{
|
||||
u3_noun cab = b;
|
||||
c3_w pos_w = 0;
|
||||
c3_w pos_w = 0;
|
||||
|
||||
while ( 0 != cab ) {
|
||||
u3_noun h_cab = u3h(cab);
|
||||
c3_w len_w = u3r_met(a_g, h_cab);
|
||||
|
||||
u3r_chop(a_g, 0, len_w, pos_w, sal_w, h_cab);
|
||||
u3r_chop(a_g, 0, len_w, pos_w, sab_u.buf_w, h_cab);
|
||||
pos_w += len_w;
|
||||
cab = u3t(cab);
|
||||
}
|
||||
}
|
||||
// return u3a_moot(sal_w);
|
||||
return u3a_malt(sal_w);
|
||||
|
||||
return u3i_slab_mint(&sab_u);
|
||||
}
|
||||
}
|
||||
u3_noun
|
||||
|
@ -14,9 +14,9 @@
|
||||
return u3m_bail(c3__exit);
|
||||
}
|
||||
else {
|
||||
c3_g a_g = a;
|
||||
c3_w tot_w = 0;
|
||||
c3_w* sal_w;
|
||||
c3_g a_g = a;
|
||||
c3_w tot_w = 0;
|
||||
u3i_slab sab_u;
|
||||
|
||||
/* Measure and validate the slab required.
|
||||
*/
|
||||
@ -42,30 +42,30 @@
|
||||
tot_w++;
|
||||
cab = u3t(cab);
|
||||
}
|
||||
|
||||
if ( 0 == tot_w ) {
|
||||
return 0;
|
||||
}
|
||||
if ( 0 == (sal_w = u3a_slaq(a_g, tot_w)) ) {
|
||||
return u3m_bail(c3__fail);
|
||||
}
|
||||
|
||||
u3i_slab_init(&sab_u, a_g, tot_w);
|
||||
}
|
||||
|
||||
/* Chop the list atoms in.
|
||||
*/
|
||||
{
|
||||
u3_noun cab = b;
|
||||
c3_w pos_w = 0;
|
||||
c3_w pos_w = 0;
|
||||
|
||||
while ( 0 != cab ) {
|
||||
u3_noun h_cab = u3h(cab);
|
||||
|
||||
u3r_chop(a_g, 0, 1, pos_w, sal_w, h_cab);
|
||||
u3r_chop(a_g, 0, 1, pos_w, sab_u.buf_w, h_cab);
|
||||
pos_w++;
|
||||
cab = u3t(cab);
|
||||
}
|
||||
}
|
||||
// return u3a_moot(sal_w);
|
||||
return u3a_malt(sal_w);
|
||||
|
||||
return u3i_slab_mint(&sab_u);
|
||||
}
|
||||
}
|
||||
u3_noun
|
||||
|
@ -28,19 +28,8 @@ u3qc_repn(u3_atom bits, u3_noun blox)
|
||||
c3_w num_blox_w = u3qb_lent(blox);
|
||||
c3_w bit_widt_w = num_blox_w * bits;
|
||||
c3_w wor_widt_w = DIVCEIL(bit_widt_w, 32);
|
||||
|
||||
//
|
||||
// Allocate a proto-atom. This is u3a_slab without initialization.
|
||||
//
|
||||
c3_w* buf_w;
|
||||
{
|
||||
c3_w* nov_w = u3a_walloc(wor_widt_w + c3_wiseof(u3a_atom));
|
||||
u3a_atom* pug_u = (void *)nov_w;
|
||||
|
||||
pug_u->mug_w = 0;
|
||||
pug_u->len_w = wor_widt_w;
|
||||
buf_w = pug_u->buf_w;
|
||||
}
|
||||
u3i_slab sab_u;
|
||||
u3i_slab_bare(&sab_u, 5, wor_widt_w);
|
||||
|
||||
//
|
||||
// Fill the atom buffer with bits from each block.
|
||||
@ -53,7 +42,7 @@ u3qc_repn(u3_atom bits, u3_noun blox)
|
||||
// cur_w next buffer word to flush into.
|
||||
//
|
||||
{
|
||||
c3_w acc_w=0, use_w=0, *cur_w=buf_w;
|
||||
c3_w acc_w=0, use_w=0, *cur_w=sab_u.buf_w;
|
||||
|
||||
# define FLUSH() *cur_w++=acc_w; acc_w=use_w=0
|
||||
# define SLICE(sz,off,val) TAKEBITS(sz, val) << off
|
||||
@ -98,7 +87,7 @@ u3qc_repn(u3_atom bits, u3_noun blox)
|
||||
}
|
||||
}
|
||||
|
||||
return u3a_malt(buf_w);
|
||||
return u3i_slab_mint(&sab_u);
|
||||
}
|
||||
|
||||
u3_noun
|
||||
|
@ -42,23 +42,19 @@ u3_noun u3qc_rip(u3_atom bloq, u3_atom b) {
|
||||
c3_w tub_w = ((dif_w == 0) ? san_w : (san_w - dif_w));
|
||||
|
||||
for ( c3_w i_w = 0; i_w < met_w; i_w++ ) {
|
||||
c3_w pat_w = (met_w - (i_w + 1));
|
||||
c3_w wut_w = (pat_w << san_g);
|
||||
c3_w sap_w = ((0 == i_w) ? tub_w : san_w);
|
||||
c3_w* sal_w = u3a_slab(sap_w);
|
||||
|
||||
if ( 0 == sal_w ) {
|
||||
return u3m_bail(c3__fail);
|
||||
}
|
||||
|
||||
c3_w j_w;
|
||||
u3_atom rip;
|
||||
c3_w pat_w = (met_w - (i_w + 1));
|
||||
c3_w wut_w = (pat_w << san_g);
|
||||
c3_w sap_w = ((0 == i_w) ? tub_w : san_w);
|
||||
c3_w j_w;
|
||||
u3_atom rip;
|
||||
u3i_slab sab_u;
|
||||
u3i_slab_bare(&sab_u, 5, sap_w);
|
||||
|
||||
for ( j_w = 0; j_w < sap_w; j_w++ ) {
|
||||
sal_w[j_w] = u3r_word(wut_w + j_w, b);
|
||||
sab_u.buf_w[j_w] = u3r_word(wut_w + j_w, b);
|
||||
}
|
||||
|
||||
rip = u3a_malt(sal_w);
|
||||
rip = u3i_slab_mint(&sab_u);
|
||||
acc = u3nc(rip, acc);
|
||||
len_w -= san_w;
|
||||
}
|
||||
|
@ -26,15 +26,12 @@
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
c3_w* sal_w = u3a_slaq(a_g, (len_w - b_w));
|
||||
u3i_slab sab_u;
|
||||
u3i_slab_init(&sab_u, a_g, (len_w - b_w));
|
||||
|
||||
if ( 0 == sal_w ) {
|
||||
return u3m_bail(c3__fail);
|
||||
}
|
||||
u3r_chop(a_g, b_w, (len_w - b_w), 0, sal_w, c);
|
||||
u3r_chop(a_g, b_w, (len_w - b_w), 0, sab_u.buf_w, c);
|
||||
|
||||
// return u3a_moot(sal_w);
|
||||
return u3a_malt(sal_w);
|
||||
return u3i_slab_mint(&sab_u);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,16 +37,9 @@ u3qe_jam(u3_atom a)
|
||||
}
|
||||
#endif
|
||||
|
||||
c3_w bit_w, *sal_w;
|
||||
c3_w* wor_w = u3s_jam_fib(a, &bit_w);
|
||||
c3_w len_w = bit_w >> 5;
|
||||
if ( (len_w << 5) != bit_w ) {
|
||||
++len_w;
|
||||
}
|
||||
sal_w = u3a_slab(len_w);
|
||||
memcpy(sal_w, wor_w, len_w*sizeof(c3_w));
|
||||
u3a_wfree(wor_w);
|
||||
return u3a_moot(sal_w);
|
||||
u3i_slab sab_u;
|
||||
u3s_jam_fib(&sab_u, a);
|
||||
return u3i_slab_mint(&sab_u);
|
||||
}
|
||||
|
||||
u3_noun
|
||||
|
@ -632,6 +632,28 @@ u3a_wfree(void* tox_v)
|
||||
_box_free(u3a_botox(tox_v));
|
||||
}
|
||||
|
||||
/* u3a_wtrim(): trim storage.
|
||||
*/
|
||||
void
|
||||
u3a_wtrim(void* tox_v, c3_w old_w, c3_w len_w)
|
||||
{
|
||||
c3_w* nov_w = tox_v;
|
||||
|
||||
if ( (old_w > len_w)
|
||||
&& ((old_w - len_w) >= u3a_minimum) )
|
||||
{
|
||||
c3_w* box_w = (void *)u3a_botox(nov_w);
|
||||
c3_w* end_w = (nov_w + len_w + 1);
|
||||
c3_w asz_w = (end_w - box_w);
|
||||
c3_w bsz_w = box_w[0] - asz_w;
|
||||
|
||||
_box_attach(_box_make(end_w, bsz_w, 0));
|
||||
|
||||
box_w[0] = asz_w;
|
||||
box_w[asz_w - 1] = asz_w;
|
||||
}
|
||||
}
|
||||
|
||||
/* u3a_calloc(): allocate and zero-initialize array
|
||||
*/
|
||||
void*
|
||||
@ -2457,77 +2479,6 @@ u3a_rewrite_noun(u3_noun som)
|
||||
cel->tel = u3a_rewritten_noun(cel->tel);
|
||||
}
|
||||
|
||||
/* u3a_slab(): create a length-bounded proto-atom.
|
||||
*/
|
||||
c3_w*
|
||||
u3a_slab(c3_w len_w)
|
||||
{
|
||||
c3_w* nov_w = u3a_walloc(len_w + c3_wiseof(u3a_atom));
|
||||
u3a_atom* pug_u = (void *)nov_w;
|
||||
|
||||
pug_u->mug_w = 0;
|
||||
pug_u->len_w = len_w;
|
||||
|
||||
/* Clear teh slab.
|
||||
*/
|
||||
{
|
||||
c3_w i_w;
|
||||
|
||||
for ( i_w=0; i_w < len_w; i_w++ ) {
|
||||
pug_u->buf_w[i_w] = 0;
|
||||
}
|
||||
}
|
||||
return pug_u->buf_w;
|
||||
}
|
||||
|
||||
/* u3a_slaq(): u3a_slab() with a defined blocksize.
|
||||
*/
|
||||
c3_w*
|
||||
u3a_slaq(c3_g met_g, c3_w len_w)
|
||||
{
|
||||
return u3a_slab(((len_w << met_g) + 31) >> 5);
|
||||
}
|
||||
|
||||
/* u3a_malt(): measure and finish a proto-atom.
|
||||
*/
|
||||
u3_noun
|
||||
u3a_malt(c3_w* sal_w)
|
||||
{
|
||||
c3_w* nov_w = (sal_w - c3_wiseof(u3a_atom));
|
||||
u3a_atom* nov_u = (void *)nov_w;
|
||||
c3_w len_w;
|
||||
|
||||
for ( len_w = nov_u->len_w; len_w; len_w-- ) {
|
||||
if ( 0 != nov_u->buf_w[len_w - 1] ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return u3a_mint(sal_w, len_w);
|
||||
}
|
||||
|
||||
/* u3a_moot(): finish a pre-measured proto-atom; dangerous.
|
||||
*/
|
||||
u3_noun
|
||||
u3a_moot(c3_w* sal_w)
|
||||
{
|
||||
c3_w* nov_w = (sal_w - c3_wiseof(u3a_atom));
|
||||
u3a_atom* nov_u = (void*)nov_w;
|
||||
c3_w len_w = nov_u->len_w;
|
||||
c3_w las_w = nov_u->buf_w[len_w - 1];
|
||||
|
||||
c3_assert(0 != len_w);
|
||||
c3_assert(0 != las_w);
|
||||
|
||||
if ( 1 == len_w ) {
|
||||
if ( _(u3a_is_cat(las_w)) ) {
|
||||
u3a_wfree(nov_w);
|
||||
|
||||
return las_w;
|
||||
}
|
||||
}
|
||||
return u3a_to_pug(u3a_outa(nov_w));
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* _ca_detect(): in u3a_detect().
|
||||
*/
|
||||
@ -2574,53 +2525,6 @@ u3a_detect(u3_noun fum, u3_noun som)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* u3a_mint(): finish a measured proto-atom.
|
||||
*/
|
||||
u3_noun
|
||||
u3a_mint(c3_w* sal_w, c3_w len_w)
|
||||
{
|
||||
c3_w* nov_w = (sal_w - c3_wiseof(u3a_atom));
|
||||
u3a_atom* nov_u = (void*)nov_w;
|
||||
|
||||
/* See if we can free the slab entirely.
|
||||
*/
|
||||
if ( len_w == 0 ) {
|
||||
u3a_wfree(nov_w);
|
||||
|
||||
return 0;
|
||||
}
|
||||
else if ( len_w == 1 ) {
|
||||
c3_w low_w = nov_u->buf_w[0];
|
||||
|
||||
if ( _(u3a_is_cat(low_w)) ) {
|
||||
u3a_wfree(nov_w);
|
||||
|
||||
return low_w;
|
||||
}
|
||||
}
|
||||
|
||||
/* See if we can strip off a block on the end.
|
||||
*/
|
||||
{
|
||||
c3_w old_w = nov_u->len_w;
|
||||
c3_w dif_w = (old_w - len_w);
|
||||
|
||||
if ( dif_w >= u3a_minimum ) {
|
||||
c3_w* box_w = (void *)u3a_botox(nov_w);
|
||||
c3_w* end_w = (nov_w + c3_wiseof(u3a_atom) + len_w + 1);
|
||||
c3_w asz_w = (end_w - box_w);
|
||||
c3_w bsz_w = box_w[0] - asz_w;
|
||||
|
||||
_box_attach(_box_make(end_w, bsz_w, 0));
|
||||
|
||||
box_w[0] = asz_w;
|
||||
box_w[asz_w - 1] = asz_w;
|
||||
}
|
||||
nov_u->len_w = len_w;
|
||||
}
|
||||
return u3a_to_pug(u3a_outa(nov_w));
|
||||
}
|
||||
|
||||
#ifdef U3_MEMORY_DEBUG
|
||||
/* u3a_lush(): leak push.
|
||||
*/
|
||||
|
@ -3,126 +3,382 @@
|
||||
*/
|
||||
#include "all.h"
|
||||
|
||||
/* u3i_bytes(): Copy [a] bytes from [b] to an LSB first atom.
|
||||
/* _ci_slab_size(): calculate slab bloq-size, checking for overflow.
|
||||
*/
|
||||
u3_noun
|
||||
u3i_bytes(c3_w a_w,
|
||||
const c3_y* b_y)
|
||||
static c3_w
|
||||
_ci_slab_size(c3_g met_g, c3_d len_d)
|
||||
{
|
||||
u3_noun pro;
|
||||
c3_d bit_d = len_d << met_g;
|
||||
c3_d wor_d = (bit_d + 0x1f) >> 5;
|
||||
c3_w wor_w = (c3_w)wor_d;
|
||||
|
||||
// Strip trailing zeroes.
|
||||
//
|
||||
while ( a_w && !b_y[a_w - 1] ) {
|
||||
a_w--;
|
||||
if ( (wor_w != wor_d)
|
||||
|| (len_d != (bit_d >> met_g)) )
|
||||
{
|
||||
return (c3_w)u3m_bail(c3__fail);
|
||||
}
|
||||
|
||||
// Check for cat.
|
||||
return wor_w;
|
||||
}
|
||||
|
||||
/* _ci_slab_init(): initialize slab with heap allocation.
|
||||
** NB: callers must ensure [len_w] >0
|
||||
*/
|
||||
static void
|
||||
_ci_slab_init(u3i_slab* sab_u, c3_w len_w)
|
||||
{
|
||||
c3_w* nov_w = u3a_walloc(len_w + c3_wiseof(u3a_atom));
|
||||
u3a_atom* vat_u = (void *)nov_w;
|
||||
|
||||
vat_u->mug_w = 0;
|
||||
vat_u->len_w = len_w;
|
||||
|
||||
#ifdef U3_MEMORY_DEBUG
|
||||
c3_assert( len_w );
|
||||
#endif
|
||||
|
||||
sab_u->_._vat_u = vat_u;
|
||||
sab_u->buf_w = vat_u->buf_w;
|
||||
sab_u->len_w = len_w;
|
||||
}
|
||||
|
||||
/* _ci_slab_grow(): update slab with heap reallocation.
|
||||
*/
|
||||
static void
|
||||
_ci_slab_grow(u3i_slab* sab_u, c3_w len_w)
|
||||
{
|
||||
c3_w* old_w = (void*)sab_u->_._vat_u;
|
||||
// XX implement a more efficient u3a_wealloc()
|
||||
//
|
||||
if ( a_w <= 4 ) {
|
||||
if ( !a_w ) {
|
||||
return 0;
|
||||
}
|
||||
else if ( a_w == 1 ) {
|
||||
return b_y[0];
|
||||
}
|
||||
else if ( a_w == 2 ) {
|
||||
return (b_y[0] | (b_y[1] << 8));
|
||||
}
|
||||
else if ( a_w == 3 ) {
|
||||
return (b_y[0] | (b_y[1] << 8) | (b_y[2] << 16));
|
||||
}
|
||||
else if ( (b_y[3] <= 0x7f) ) {
|
||||
return (b_y[0] | (b_y[1] << 8) | (b_y[2] << 16) | (b_y[3] << 24));
|
||||
c3_w* nov_w = u3a_wealloc(old_w, len_w + c3_wiseof(u3a_atom));
|
||||
u3a_atom* vat_u = (void *)nov_w;
|
||||
|
||||
vat_u->len_w = len_w;
|
||||
|
||||
sab_u->_._vat_u = vat_u;
|
||||
sab_u->buf_w = vat_u->buf_w;
|
||||
sab_u->len_w = len_w;
|
||||
}
|
||||
|
||||
/* _ci_atom_mint(): finalize a heap-allocated atom at specified length.
|
||||
*/
|
||||
static u3_atom
|
||||
_ci_atom_mint(u3a_atom* vat_u, c3_w len_w)
|
||||
{
|
||||
c3_w* nov_w = (void*)vat_u;
|
||||
|
||||
if ( 0 == len_w ) {
|
||||
u3a_wfree(nov_w);
|
||||
return (u3_atom)0;
|
||||
}
|
||||
else if ( 1 == len_w ) {
|
||||
c3_w dat_w = *vat_u->buf_w;
|
||||
|
||||
if ( c3y == u3a_is_cat(dat_w) ) {
|
||||
u3a_wfree(nov_w);
|
||||
return (u3_atom)dat_w;
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate, fill, return.
|
||||
// try to strip a block off the end
|
||||
//
|
||||
{
|
||||
c3_w old_w = vat_u->len_w;
|
||||
|
||||
if ( old_w > len_w ) {
|
||||
c3_y wiz_y = c3_wiseof(u3a_atom);
|
||||
u3a_wtrim(nov_w, old_w + wiz_y, len_w + wiz_y);
|
||||
}
|
||||
}
|
||||
|
||||
vat_u->len_w = len_w;
|
||||
|
||||
return u3a_to_pug(u3a_outa(nov_w));
|
||||
}
|
||||
|
||||
/* u3i_slab_init(): configure bloq-length slab, zero-initialize.
|
||||
*/
|
||||
void
|
||||
u3i_slab_init(u3i_slab* sab_u, c3_g met_g, c3_d len_d)
|
||||
{
|
||||
u3i_slab_bare(sab_u, met_g, len_d);
|
||||
|
||||
u3t_on(mal_o);
|
||||
memset(sab_u->buf_y, 0, (size_t)sab_u->len_w * 4);
|
||||
u3t_off(mal_o);
|
||||
}
|
||||
|
||||
/* u3i_slab_bare(): configure bloq-length slab, uninitialized.
|
||||
*/
|
||||
void
|
||||
u3i_slab_bare(u3i_slab* sab_u, c3_g met_g, c3_d len_d)
|
||||
{
|
||||
u3t_on(mal_o);
|
||||
{
|
||||
c3_w len_w = (a_w + 3) >> 2;
|
||||
c3_w* nov_w = u3a_walloc((len_w + c3_wiseof(u3a_atom)));
|
||||
u3a_atom* nov_u = (void*)nov_w;
|
||||
c3_w wor_w = _ci_slab_size(met_g, len_d);
|
||||
|
||||
nov_u->mug_w = 0;
|
||||
nov_u->len_w = len_w;
|
||||
|
||||
// Clear the words.
|
||||
// if we only need one word, use the static storage in [sab_u]
|
||||
//
|
||||
{
|
||||
c3_w i_w;
|
||||
|
||||
for ( i_w=0; i_w < len_w; i_w++ ) {
|
||||
nov_u->buf_w[i_w] = 0;
|
||||
}
|
||||
if ( (0 == wor_w) || (1 == wor_w) ) {
|
||||
sab_u->_._vat_u = 0;
|
||||
sab_u->buf_w = &sab_u->_._sat_w;
|
||||
sab_u->len_w = 1;
|
||||
}
|
||||
|
||||
// Fill the bytes.
|
||||
// allocate an indirect atom
|
||||
//
|
||||
{
|
||||
c3_w i_w;
|
||||
|
||||
for ( i_w=0; i_w < a_w; i_w++ ) {
|
||||
nov_u->buf_w[i_w >> 2] |= (b_y[i_w] << ((i_w & 3) * 8));
|
||||
}
|
||||
else {
|
||||
_ci_slab_init(sab_u, wor_w);
|
||||
}
|
||||
|
||||
pro = u3a_to_pug(u3a_outa(nov_w));
|
||||
}
|
||||
u3t_off(mal_o);
|
||||
}
|
||||
|
||||
/* u3i_slab_from(): configure bloq-length slab, initialize with [a].
|
||||
*/
|
||||
void
|
||||
u3i_slab_from(u3i_slab* sab_u, u3_atom a, c3_g met_g, c3_d len_d)
|
||||
{
|
||||
u3i_slab_bare(sab_u, met_g, len_d);
|
||||
|
||||
// copies [a], zero-initializes any additional space
|
||||
//
|
||||
u3r_words(0, sab_u->len_w, sab_u->buf_w, a);
|
||||
}
|
||||
|
||||
/* u3i_slab_grow(): resize slab, zero-initializing new space.
|
||||
*/
|
||||
void
|
||||
u3i_slab_grow(u3i_slab* sab_u, c3_g met_g, c3_d len_d)
|
||||
{
|
||||
c3_w old_w = sab_u->len_w;
|
||||
|
||||
u3t_on(mal_o);
|
||||
{
|
||||
c3_w wor_w = _ci_slab_size(met_g, len_d);
|
||||
|
||||
// XX actually shrink?
|
||||
//
|
||||
if ( wor_w <= old_w ) {
|
||||
sab_u->len_w = wor_w;
|
||||
}
|
||||
else {
|
||||
// upgrade from static storage
|
||||
//
|
||||
if ( 1 == old_w ) {
|
||||
c3_w dat_w = *sab_u->buf_w;
|
||||
|
||||
_ci_slab_init(sab_u, wor_w);
|
||||
sab_u->buf_w[0] = dat_w;
|
||||
}
|
||||
// reallocate
|
||||
//
|
||||
else {
|
||||
_ci_slab_grow(sab_u, wor_w);
|
||||
}
|
||||
|
||||
{
|
||||
c3_y* buf_y = (void*)(sab_u->buf_w + old_w);
|
||||
size_t dif_i = wor_w - old_w;
|
||||
memset(buf_y, 0, dif_i * 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
u3t_off(mal_o);
|
||||
}
|
||||
|
||||
/* u3i_slab_free(): dispose memory backing slab.
|
||||
*/
|
||||
void
|
||||
u3i_slab_free(u3i_slab* sab_u)
|
||||
{
|
||||
c3_w len_w = sab_u->len_w;
|
||||
u3a_atom* vat_u = sab_u->_._vat_u;
|
||||
|
||||
u3t_on(mal_o);
|
||||
|
||||
if ( 1 == len_w ) {
|
||||
c3_assert( !vat_u );
|
||||
}
|
||||
else {
|
||||
c3_w* tav_w = (sab_u->buf_w - c3_wiseof(u3a_atom));
|
||||
c3_assert( tav_w == (c3_w*)vat_u );
|
||||
u3a_wfree(vat_u);
|
||||
}
|
||||
|
||||
u3t_off(mal_o);
|
||||
}
|
||||
|
||||
/* u3i_slab_mint(): produce atom from slab, trimming.
|
||||
*/
|
||||
u3_atom
|
||||
u3i_slab_mint(u3i_slab* sab_u)
|
||||
{
|
||||
c3_w len_w = sab_u->len_w;
|
||||
u3a_atom* vat_u = sab_u->_._vat_u;
|
||||
u3_atom pro;
|
||||
|
||||
u3t_on(mal_o);
|
||||
|
||||
if ( 1 == len_w ) {
|
||||
c3_w dat_w = *sab_u->buf_w;
|
||||
|
||||
c3_assert( !vat_u );
|
||||
|
||||
u3t_off(mal_o);
|
||||
pro = u3i_word(dat_w);
|
||||
u3t_on(mal_o);
|
||||
}
|
||||
else {
|
||||
u3a_atom* vat_u = sab_u->_._vat_u;
|
||||
c3_w* tav_w = (sab_u->buf_w - c3_wiseof(u3a_atom));
|
||||
c3_assert( tav_w == (c3_w*)vat_u );
|
||||
|
||||
// trim trailing zeros
|
||||
//
|
||||
while ( len_w && !(sab_u->buf_w[len_w - 1]) ) {
|
||||
len_w--;
|
||||
}
|
||||
|
||||
pro = _ci_atom_mint(vat_u, len_w);
|
||||
}
|
||||
|
||||
u3t_off(mal_o);
|
||||
|
||||
return pro;
|
||||
}
|
||||
|
||||
/* u3i_slab_moot(): produce atom from slab, no trimming.
|
||||
*/
|
||||
u3_atom
|
||||
u3i_slab_moot(u3i_slab* sab_u)
|
||||
{
|
||||
c3_w len_w = sab_u->len_w;
|
||||
u3a_atom* vat_u = sab_u->_._vat_u;
|
||||
u3_atom pro;
|
||||
|
||||
u3t_on(mal_o);
|
||||
|
||||
if ( 1 == len_w) {
|
||||
c3_w dat_w = *sab_u->buf_w;
|
||||
|
||||
c3_assert( !sab_u->_._vat_u );
|
||||
|
||||
u3t_off(mal_o);
|
||||
pro = u3i_word(dat_w);
|
||||
u3t_on(mal_o);
|
||||
}
|
||||
else {
|
||||
u3a_atom* vat_u = sab_u->_._vat_u;
|
||||
c3_w* tav_w = (sab_u->buf_w - c3_wiseof(u3a_atom));
|
||||
c3_assert( tav_w == (c3_w*)vat_u );
|
||||
|
||||
pro = _ci_atom_mint(vat_u, len_w);
|
||||
}
|
||||
|
||||
u3t_off(mal_o);
|
||||
|
||||
return pro;
|
||||
}
|
||||
|
||||
/* u3i_word(): construct u3_atom from c3_w.
|
||||
*/
|
||||
u3_atom
|
||||
u3i_word(c3_w dat_w)
|
||||
{
|
||||
u3_atom pro;
|
||||
|
||||
u3t_on(mal_o);
|
||||
|
||||
if ( c3y == u3a_is_cat(dat_w) ) {
|
||||
pro = (u3_atom)dat_w;
|
||||
}
|
||||
else {
|
||||
c3_w* nov_w = u3a_walloc(1 + c3_wiseof(u3a_atom));
|
||||
u3a_atom* vat_u = (void *)nov_w;
|
||||
|
||||
vat_u->mug_w = 0;
|
||||
vat_u->len_w = 1;
|
||||
vat_u->buf_w[0] = dat_w;
|
||||
|
||||
pro = u3a_to_pug(u3a_outa(nov_w));
|
||||
}
|
||||
|
||||
u3t_off(mal_o);
|
||||
|
||||
return pro;
|
||||
}
|
||||
|
||||
/* u3i_chub(): construct u3_atom from c3_d.
|
||||
*/
|
||||
u3_atom
|
||||
u3i_chub(c3_d dat_d)
|
||||
{
|
||||
c3_w dat_w[2] = {
|
||||
dat_d & 0xffffffffULL,
|
||||
dat_d >> 32
|
||||
};
|
||||
|
||||
return u3i_words(2, dat_w);
|
||||
}
|
||||
|
||||
/* u3i_bytes(): Copy [a] bytes from [b] to an LSB first atom.
|
||||
*/
|
||||
u3_atom
|
||||
u3i_bytes(c3_w a_w,
|
||||
const c3_y* b_y)
|
||||
{
|
||||
// strip trailing zeroes.
|
||||
//
|
||||
while ( a_w && !b_y[a_w - 1] ) {
|
||||
a_w--;
|
||||
}
|
||||
|
||||
if ( !a_w ) {
|
||||
return (u3_atom)0;
|
||||
}
|
||||
else {
|
||||
u3i_slab sab_u;
|
||||
|
||||
u3i_slab_bare(&sab_u, 3, a_w);
|
||||
|
||||
u3t_on(mal_o);
|
||||
{
|
||||
// zero-initialize last word
|
||||
//
|
||||
sab_u.buf_w[sab_u.len_w - 1] = 0;
|
||||
memcpy(sab_u.buf_y, b_y, a_w);
|
||||
}
|
||||
u3t_off(mal_o);
|
||||
|
||||
return u3i_slab_moot_bytes(&sab_u);
|
||||
}
|
||||
}
|
||||
|
||||
/* u3i_words(): Copy [a] words from [b] into an atom.
|
||||
*/
|
||||
u3_noun
|
||||
u3_atom
|
||||
u3i_words(c3_w a_w,
|
||||
const c3_w* b_w)
|
||||
{
|
||||
u3_noun pro;
|
||||
|
||||
// Strip trailing zeroes.
|
||||
// strip trailing zeroes.
|
||||
//
|
||||
while ( a_w && !b_w[a_w - 1] ) {
|
||||
a_w--;
|
||||
}
|
||||
|
||||
// Check for cat.
|
||||
//
|
||||
if ( !a_w ) {
|
||||
return 0;
|
||||
return (u3_atom)0;
|
||||
}
|
||||
else if ( (a_w == 1) && !(b_w[0] >> 31) ) {
|
||||
return b_w[0];
|
||||
else {
|
||||
u3i_slab sab_u;
|
||||
u3i_slab_bare(&sab_u, 5, a_w);
|
||||
|
||||
u3t_on(mal_o);
|
||||
memcpy(sab_u.buf_w, b_w, (size_t)4 * a_w);
|
||||
u3t_off(mal_o);
|
||||
|
||||
return u3i_slab_moot(&sab_u);
|
||||
}
|
||||
|
||||
// Allocate, fill, return.
|
||||
//
|
||||
u3t_on(mal_o);
|
||||
{
|
||||
c3_w* nov_w = u3a_walloc(a_w + c3_wiseof(u3a_atom));
|
||||
u3a_atom* nov_u = (void*)nov_w;
|
||||
|
||||
nov_u->mug_w = 0;
|
||||
nov_u->len_w = a_w;
|
||||
|
||||
// Fill the words.
|
||||
//
|
||||
{
|
||||
c3_w i_w;
|
||||
|
||||
for ( i_w=0; i_w < a_w; i_w++ ) {
|
||||
nov_u->buf_w[i_w] = b_w[i_w];
|
||||
}
|
||||
}
|
||||
|
||||
pro = u3a_to_pug(u3a_outa(nov_w));
|
||||
}
|
||||
u3t_off(mal_o);
|
||||
|
||||
return pro;
|
||||
}
|
||||
|
||||
/* u3i_chubs(): Copy [a] chubs from [b] into an atom.
|
||||
@ -131,100 +387,69 @@ u3_atom
|
||||
u3i_chubs(c3_w a_w,
|
||||
const c3_d* b_d)
|
||||
{
|
||||
u3_noun pro;
|
||||
|
||||
// Strip trailing zeroes.
|
||||
// strip trailing zeroes.
|
||||
//
|
||||
while ( a_w && !b_d[a_w - 1] ) {
|
||||
a_w--;
|
||||
}
|
||||
|
||||
// Check for cat.
|
||||
//
|
||||
if ( !a_w ) {
|
||||
return 0;
|
||||
return (u3_atom)0;
|
||||
}
|
||||
else if ( (1 == a_w) && !(b_d[0] >> 31) ) {
|
||||
return (c3_w)b_d[0];
|
||||
else if ( 1 == a_w ) {
|
||||
return u3i_chub(b_d[0]);
|
||||
}
|
||||
else {
|
||||
u3i_slab sab_u;
|
||||
u3i_slab_bare(&sab_u, 6, a_w);
|
||||
|
||||
// Allocate, fill, return.
|
||||
//
|
||||
u3t_on(mal_o);
|
||||
{
|
||||
c3_w len_w = 2 * a_w;
|
||||
|
||||
if ( !(b_d[a_w - 1] >> 32) ) {
|
||||
len_w--;
|
||||
}
|
||||
|
||||
c3_w* nov_w = u3a_walloc(len_w + c3_wiseof(u3a_atom));
|
||||
u3a_atom* nov_u = (void*)nov_w;
|
||||
|
||||
nov_u->mug_w = 0;
|
||||
nov_u->len_w = len_w;
|
||||
|
||||
// Fill the words.
|
||||
//
|
||||
u3t_on(mal_o);
|
||||
{
|
||||
c3_w i_w, x_w, max_w = a_w - 1;
|
||||
c3_d i_d;
|
||||
c3_w* buf_w = sab_u.buf_w;
|
||||
c3_w i_w;
|
||||
c3_d i_d;
|
||||
|
||||
for ( i_w = 0; i_w < max_w; i_w++ ) {
|
||||
for ( i_w = 0; i_w < a_w; i_w++ ) {
|
||||
i_d = b_d[i_w];
|
||||
x_w = 2 * i_w;
|
||||
nov_u->buf_w[x_w] = i_d & 0xffffffffULL;
|
||||
x_w++;
|
||||
nov_u->buf_w[x_w] = i_d >> 32;
|
||||
}
|
||||
|
||||
{
|
||||
i_d = b_d[i_w];
|
||||
x_w = 2 * i_w;
|
||||
nov_u->buf_w[x_w] = i_d & 0xffffffffULL;
|
||||
x_w++;
|
||||
}
|
||||
|
||||
if ( x_w < len_w ) {
|
||||
nov_u->buf_w[x_w] = i_d >> 32;
|
||||
*buf_w++ = i_d & 0xffffffffULL;
|
||||
*buf_w++ = i_d >> 32;
|
||||
}
|
||||
}
|
||||
u3t_off(mal_o);
|
||||
|
||||
pro = u3a_to_pug(u3a_outa(nov_w));
|
||||
return u3i_slab_mint(&sab_u);
|
||||
}
|
||||
u3t_off(mal_o);
|
||||
|
||||
return pro;
|
||||
}
|
||||
|
||||
/* u3i_mp(): Copy the GMP integer [a] into an atom, and clear it.
|
||||
*/
|
||||
u3_noun
|
||||
u3_atom
|
||||
u3i_mp(mpz_t a_mp)
|
||||
{
|
||||
c3_w pyg_w = mpz_size(a_mp) * ((sizeof(mp_limb_t)) / 4);
|
||||
c3_w* buz_w = u3a_slab(4 * pyg_w);
|
||||
size_t siz_i = mpz_sizeinbase(a_mp, 2);
|
||||
u3i_slab sab_u;
|
||||
u3i_slab_init(&sab_u, 0, siz_i);
|
||||
|
||||
mpz_export(buz_w, 0, -1, sizeof(c3_w), 0, 0, a_mp);
|
||||
mpz_export(sab_u.buf_w, 0, -1, sizeof(c3_w), 0, 0, a_mp);
|
||||
mpz_clear(a_mp);
|
||||
|
||||
return u3a_malt(buz_w);
|
||||
// per the mpz_export() docs:
|
||||
//
|
||||
// > If op is non-zero then the most significant word produced
|
||||
// > will be non-zero.
|
||||
//
|
||||
return u3i_slab_moot(&sab_u);
|
||||
}
|
||||
|
||||
/* u3i_vint(): increment [a].
|
||||
*/
|
||||
u3_noun
|
||||
u3_atom
|
||||
u3i_vint(u3_noun a)
|
||||
{
|
||||
c3_assert(u3_none != a);
|
||||
|
||||
if ( _(u3a_is_cat(a)) ) {
|
||||
c3_w vin_w = (a + 1);
|
||||
|
||||
if ( a == 0x7fffffff ) {
|
||||
return u3i_words(1, &vin_w);
|
||||
}
|
||||
else return vin_w;
|
||||
return ( a == 0x7fffffff ) ? u3i_word(a + 1) : (a + 1);
|
||||
}
|
||||
else if ( _(u3a_is_cell(a)) ) {
|
||||
return u3m_bail(c3__exit);
|
||||
|
@ -121,18 +121,14 @@ _cj_bash(u3_noun bat)
|
||||
rod_u = u3to(u3_road, rod_u->par_p);
|
||||
}
|
||||
else {
|
||||
c3_w bit_w, met_w;
|
||||
c3_w* wor_w;
|
||||
c3_y* fat_y;
|
||||
c3_y dig_y[32];
|
||||
u3i_slab sab_u;
|
||||
c3_w bit_w = u3s_jam_fib(&sab_u, bat);
|
||||
c3_w met_w = (bit_w + 0x7) >> 3;
|
||||
// XX assumes little-endian
|
||||
//
|
||||
c3_y* fat_y = sab_u.buf_y;
|
||||
c3_y dig_y[32];
|
||||
|
||||
wor_w = u3s_jam_fib(bat, &bit_w);
|
||||
met_w = bit_w >> 3;
|
||||
if ( bit_w != met_w << 3 ) {
|
||||
++met_w;
|
||||
}
|
||||
// assume little-endian
|
||||
fat_y = (c3_y*) wor_w;
|
||||
#if defined(U3_OS_osx)
|
||||
CC_SHA256_CTX ctx_h;
|
||||
|
||||
@ -146,9 +142,10 @@ _cj_bash(u3_noun bat)
|
||||
SHA256_Update(&ctx_h, fat_y, met_w);
|
||||
SHA256_Final(dig_y, &ctx_h);
|
||||
#endif
|
||||
|
||||
pro = u3i_bytes(32, dig_y);
|
||||
u3h_put(u3R->jed.bas_p, bat, u3k(pro));
|
||||
u3a_wfree(wor_w);
|
||||
u3i_slab_free(&sab_u);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -8,21 +8,14 @@
|
||||
#include "all.h"
|
||||
#include "ur/ur.h"
|
||||
|
||||
/* _cs_met0_w(): safe bitwidth for any c3_w
|
||||
*/
|
||||
static inline c3_w
|
||||
_cs_met0_w(c3_w wid_w) {
|
||||
return ( wid_w >> 31 ) ? 32 : u3r_met(0, wid_w);
|
||||
}
|
||||
|
||||
/* _cs_jam_buf: struct for tracking the fibonacci-allocated jam of a noun
|
||||
*/
|
||||
struct _cs_jam_fib {
|
||||
u3i_slab* sab_u;
|
||||
u3p(u3h_root) har_p;
|
||||
c3_w a_w;
|
||||
c3_w b_w;
|
||||
c3_w bit_w;
|
||||
c3_w* buf_w;
|
||||
};
|
||||
|
||||
/* _cs_jam_fib_grow(): reallocate buffer with fibonacci growth
|
||||
@ -39,12 +32,8 @@ _cs_jam_fib_grow(struct _cs_jam_fib* fib_u, c3_w mor_w)
|
||||
}
|
||||
|
||||
if ( wan_w > fib_u->a_w ) {
|
||||
c3_w old_w, new_w, c_w = 0;
|
||||
|
||||
old_w = fib_u->a_w >> 5;
|
||||
if ( (old_w << 5) != fib_u->a_w ) {
|
||||
++old_w;
|
||||
}
|
||||
c3_w old_w = fib_u->sab_u->len_w;
|
||||
c3_w c_w = 0;
|
||||
|
||||
// fibonacci growth
|
||||
//
|
||||
@ -54,13 +43,7 @@ _cs_jam_fib_grow(struct _cs_jam_fib* fib_u, c3_w mor_w)
|
||||
fib_u->a_w = c_w;
|
||||
}
|
||||
|
||||
new_w = c_w >> 5;
|
||||
if ( (new_w << 5) != c_w ) {
|
||||
++new_w;
|
||||
}
|
||||
|
||||
fib_u->buf_w = u3a_wealloc(fib_u->buf_w, new_w);
|
||||
memset(fib_u->buf_w + old_w, 0, (new_w - old_w) * sizeof(c3_w));
|
||||
u3i_slab_grow(fib_u->sab_u, 0, c_w);
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,8 +54,12 @@ _cs_jam_fib_chop(struct _cs_jam_fib* fib_u, c3_w met_w, u3_noun a)
|
||||
{
|
||||
c3_w bit_w = fib_u->bit_w;
|
||||
_cs_jam_fib_grow(fib_u, met_w);
|
||||
u3r_chop(0, 0, met_w, bit_w, fib_u->buf_w, a);
|
||||
fib_u->bit_w += met_w;
|
||||
|
||||
{
|
||||
c3_w* buf_w = fib_u->sab_u->buf_w;
|
||||
u3r_chop(0, 0, met_w, bit_w, buf_w, a);
|
||||
}
|
||||
}
|
||||
|
||||
/* _cs_jam_fib_mat(): length-prefixed encode (mat) [a] into [fib_u]
|
||||
@ -85,7 +72,7 @@ _cs_jam_fib_mat(struct _cs_jam_fib* fib_u, u3_noun a)
|
||||
}
|
||||
else {
|
||||
c3_w a_w = u3r_met(0, a);
|
||||
c3_w b_w = _cs_met0_w(a_w);
|
||||
c3_w b_w = c3_bits_word(a_w);
|
||||
|
||||
_cs_jam_fib_chop(fib_u, b_w+1, 1 << b_w);
|
||||
_cs_jam_fib_chop(fib_u, b_w-1, a_w & ((1 << (b_w-1)) - 1));
|
||||
@ -156,28 +143,21 @@ _cs_jam_fib_cell_cb(u3_noun a, void* ptr_v)
|
||||
** returns atom-suitable words, and *bit_w will have
|
||||
** the length (in bits). return should be freed with u3a_wfree().
|
||||
*/
|
||||
c3_w*
|
||||
u3s_jam_fib(u3_noun a, c3_w* bit_w)
|
||||
c3_w
|
||||
u3s_jam_fib(u3i_slab* sab_u, u3_noun a)
|
||||
{
|
||||
struct _cs_jam_fib fib_u;
|
||||
fib_u.har_p = u3h_new();
|
||||
fib_u.sab_u = sab_u;
|
||||
|
||||
// fib(12) is small enough to be reasonably fast to allocate.
|
||||
//
|
||||
fib_u.a_w = 144;
|
||||
// fib(11) is needed to get fib(13).
|
||||
//
|
||||
fib_u.b_w = 89;
|
||||
//
|
||||
fib_u.a_w = ur_fib12;
|
||||
fib_u.b_w = ur_fib11;
|
||||
fib_u.bit_w = 0;
|
||||
|
||||
{
|
||||
c3_w len_w = fib_u.a_w >> 5;
|
||||
if ( (len_w << 5) != fib_u.a_w ) {
|
||||
++len_w;
|
||||
}
|
||||
|
||||
fib_u.buf_w = u3a_walloc(len_w);
|
||||
memset(fib_u.buf_w, 0, len_w * sizeof(c3_w));
|
||||
}
|
||||
u3i_slab_init(sab_u, 0, fib_u.a_w);
|
||||
|
||||
// as this is a hot path, we unsafely elide overflow checks
|
||||
//
|
||||
@ -186,9 +166,9 @@ u3s_jam_fib(u3_noun a, c3_w* bit_w)
|
||||
u3a_walk_fore_unsafe(a, &fib_u, _cs_jam_fib_atom_cb,
|
||||
_cs_jam_fib_cell_cb);
|
||||
|
||||
*bit_w = fib_u.bit_w;
|
||||
u3h_free(fib_u.har_p);
|
||||
return fib_u.buf_w;
|
||||
|
||||
return fib_u.bit_w;
|
||||
}
|
||||
|
||||
typedef struct _jam_xeno_s {
|
||||
@ -602,27 +582,18 @@ _cs_cue_xeno_next(u3a_pile* pil_u,
|
||||
if ( 31 >= len_d ) {
|
||||
*out = (u3_noun)ur_bsr32_any(red_u, len_d);
|
||||
}
|
||||
// XX need a ur_bsr_words_any()
|
||||
//
|
||||
else {
|
||||
c3_w* wor_w;
|
||||
c3_y* byt_y;
|
||||
c3_d byt_d = (len_d + 0x7) >> 3;
|
||||
u3i_slab sab_u;
|
||||
|
||||
{
|
||||
c3_d byt_d = (len_d >> 3) + !!ur_mask_3(len_d);
|
||||
|
||||
if ( 0xffffffffULL < byt_d) {
|
||||
return ur_cue_meme;
|
||||
}
|
||||
|
||||
// XX assumes little-endian
|
||||
//
|
||||
wor_w = u3a_slaq(3, byt_d);
|
||||
byt_y = (c3_y*)wor_w;
|
||||
if ( 0xffffffffULL < byt_d) {
|
||||
return ur_cue_meme;
|
||||
}
|
||||
else {
|
||||
u3i_slab_init(&sab_u, 3, byt_d);
|
||||
ur_bsr_bytes_any(red_u, len_d, sab_u.buf_y);
|
||||
*out = u3i_slab_mint_bytes(&sab_u);
|
||||
}
|
||||
|
||||
ur_bsr_bytes_any(red_u, len_d, byt_y);
|
||||
*out = u3a_malt(wor_w);
|
||||
}
|
||||
|
||||
ur_dict32_put(rot_u, dic_u, bit_d, *out);
|
||||
@ -863,27 +834,12 @@ _cs_cue_bytes_next(u3a_pile* pil_u,
|
||||
if ( 31 >= len_d ) {
|
||||
vat = (u3_noun)ur_bsr32_any(red_u, len_d);
|
||||
}
|
||||
// XX need a ur_bsr_words_any()
|
||||
//
|
||||
else {
|
||||
c3_w* wor_w;
|
||||
c3_y* byt_y;
|
||||
u3i_slab sab_u;
|
||||
u3i_slab_init(&sab_u, 0, len_d);
|
||||
|
||||
{
|
||||
c3_d byt_d = (len_d >> 3) + !!ur_mask_3(len_d);
|
||||
|
||||
if ( 0xffffffffULL < byt_d) {
|
||||
return u3m_bail(c3__meme);
|
||||
}
|
||||
|
||||
// XX assumes little-endian
|
||||
//
|
||||
wor_w = u3a_slaq(3, byt_d);
|
||||
byt_y = (c3_y*)wor_w;
|
||||
}
|
||||
|
||||
ur_bsr_bytes_any(red_u, len_d, byt_y);
|
||||
vat = u3a_malt(wor_w);
|
||||
ur_bsr_bytes_any(red_u, len_d, sab_u.buf_y);
|
||||
vat = u3i_slab_mint_bytes(&sab_u);
|
||||
}
|
||||
|
||||
return _cs_cue_put(har_p, bit_d, vat);
|
||||
|
@ -338,13 +338,13 @@ _test_jam_spec(const c3_c* cap_c,
|
||||
}
|
||||
|
||||
{
|
||||
c3_w bit_w;
|
||||
c3_w* wor_w = u3s_jam_fib(ref, &bit_w);
|
||||
u3i_slab sab_u;
|
||||
c3_w bit_w = u3s_jam_fib(&sab_u, ref);
|
||||
|
||||
out_d = (bit_w >> 3) + !!ur_mask_3(bit_w);
|
||||
out_d = ((c3_d)bit_w + 0x7) >> 3;
|
||||
// XX assumes little-endian
|
||||
//
|
||||
out_y = (c3_y*)wor_w;
|
||||
out_y = sab_u.buf_y;
|
||||
|
||||
if ( 0 != memcmp(out_y, byt_y, len_w) ) {
|
||||
fprintf(stderr, "\033[31mjam fib %s fail\033[0m\r\n", cap_c);
|
||||
@ -352,7 +352,7 @@ _test_jam_spec(const c3_c* cap_c,
|
||||
ret_i = 0;
|
||||
}
|
||||
|
||||
u3a_wfree(wor_w);
|
||||
u3i_slab_free(&sab_u);
|
||||
}
|
||||
|
||||
return ret_i;
|
||||
|
Loading…
Reference in New Issue
Block a user