view mbx.c @ 0:e0bbaa717f41 draft default tip

lol J
author Jordi Gutiérrez Hermoso <jordigh@octave.org>
date Mon, 25 Nov 2013 11:56:30 -0500
parents
children
line wrap: on
line source

/* Copyright 1990-2011, Jsoftware Inc.  All rights reserved. */
/* License in license.txt.                                   */
/*                                                                         */
/* Memory-Mapped Boxed Arrays                                              */

#include "j.h"


/* A SMM array w is laid-out as follows:                                   */
/*                                                                         */
/* Initial part of w is like a regular array of type A                     */
/* Following this part (after the ravel of w) is the SMM area              */
/* Let u point to the first byte of the SMM area                           */
/*                                                                         */
/* length        usage                                                     */
/* 4*AH          J array header; flag has AFNJA bit                        */
/* 4*64          shape padded to rank of 64                                */
/* 4*n           array elements, offsets from w                            */ 
/* ...                                                                     */
/* 4*MLEN        mfree pointers                                            */
/*                                                                         */
/* each SMM array entry has the usual MS*x fields,                         */
/*   j: mfree/msize index                                                  */
/*   a: pointer to next block (when in free list)                          */
/*      w-x                   (when allocated)                             */

#define SMMCTOTAL       0
#define SMMCINUSE       1
#define SMMCFREE        2

#define RMBX            64L                                  /* max rank for mbx      */
#define SMMFREE(a)      (I**)((I)(a)+8*(AM(a)/8)-SZI*MLEN)   /* address of free lists */

static F1(jtsmmblkf);


static I smmsize(A a){
 R 8*(AM(a)/8)-SZI*(AH+RMBX+MLEN)-SZA*AN(a)-SZI*((AH+RMBX+MLEN+AN(a))%2);
}    /* size of allocateable area */

static C*smmu(A a){I v;
 v=(I)(a)+SZI*(AH+RMBX)+AN(a)*SZA;  /* 1st allocateable address   */
 R (C*)(((4+v)>>3)<<3);             /* ensure double word aligned */
}    /* first allocateable address */

static B jtsmminit(J jt,A a){C*u;I j,k,**mfree,n;MS*x;
 n=smmsize(a);
 ASSERT(0<n,EVALLOC);
 k=64; j=6; n=n>>j;
 mfree=SMMFREE(a); DO(MLEN, mfree[i]=0;);
 u=smmu(a);
 while(n){
  if(1&n){x=(MS*)u; x->j=(C)j; x->a=0; mfree[j]=(I*)AREL(x,a); u+=k;}
  n>>=1; k+=k; ++j;
 }
 R 1;
}    /* initialize SMM area */


void smmfrr(A w){A a;A1*wv;I j,**mfree;MS*x;
 x=(MS*)w-1;
 a=(A)AABS(x,x->a);
 j=x->j;
 if(BOX&AT(w)){wv=A1AV(w); DO(AN(w), smmfrr((A)AABS(w,wv[i])););}
 mfree=SMMFREE(a);
 x->a=mfree[j]; 
 mfree[j]=(I*)AREL(x,a);
}    /* free */


static B smmsplit(A a,I j){I i,k,**mfree,p;MS*x,*y;
 mfree=SMMFREE(a); p=MLEN;
 i=j;
 while(p>i&&!mfree[i])++i;
 RZ(p>i);
 k=msize[i-1];
 while(j<i){
  x=(MS*)AABS(a,mfree[i]);
  mfree[i]=x->a;
  y=(MS*)(k+(C*)x); y->a=0; y->j=(S)(i-1);
  x->a=(I*)AREL(y,a); x->j=(S)(i-1);
  mfree[i-1]=(I*)AREL(x,a);
  --i; k>>=1;
 }
 R 1;
}    /* ensure mfree[j] has a free block by splitting larger blocks */

static void smmput1(A a,I**mfree,I n,C*v){I j,k;MS*x;
 k=64; j=6; n>>=j;
 while(n){
  if(1&n){x=(MS*)v; x->j=(C)j; x->a=mfree[j]; mfree[j]=(I*)AREL(x,a); v+=k;}
  n>>=1; k+=k; ++j; 
}}   /* put block v of size n into free list(s) */

static B jtsmmjoin(J jt,A a,I j){A y;I m,**mfree,n,*p,*q;
 RZ(y=smmblkf(a));
 n=*AS(y);
 RZ(1<n);
 RZ(y=grade2(y,y));
 p=q=AV(y); m=0;
 DO(n-1, if(p[2]==p[0]+p[1])q[1]+=p[3]; else{q+=2; q[0]=p[2]; q[1]=p[3]; ++m;} p+=2;);
 ++m;
 mfree=SMMFREE(a); DO(MLEN, mfree[i]=0;);
 p=AV(y);
 DO(m, smmput1(a,mfree,p[1],(C*)p[0]); p+=2;);
 R mfree[j]||smmsplit(a,j);
}    /* ensure mfree[j] has a free block by joining smaller blocks */

static A jtsmma(J jt,A a,I m){A z;I j,n,**mfree,p;MS*x;
 JBREAK0;
 n=p=m+mhb; 
 ASSERT(n<=jt->mmax,EVLIMIT);
 j=6; n>>=j; while(n){n>>=1; ++j;}
 if(p==msize[j-1])--j;
 mfree=SMMFREE(a);
 ASSERT(mfree[j]||smmsplit(a,j)||smmjoin(a,j),EVALLOC);
 x=(MS*)AABS(a,mfree[j]);
 z=(A)(1+x); 
 mfree[j]=x->a;
 x->a=(I*)AREL(a,x);
 R z;
}    /* allocate */


static A jtsmmga(J jt,A a,I t,I n,I r,I*s){A z;I m,w;
 w=WP(t,n,r); m=SZI*w; 
 ASSERT(RMAX>=r&&m>n&&n>=0&&m>w&&w>0,EVLIMIT);   /* beware integer overflow */
 RZ(z=smma(a,m));
 AT(z)=t; ACX(z); AN(z)=n; AR(z)=r; AFLAG(z)=AFSMM; AK(z)=AKX(z); AM(z)=m-AK(z); 
 if(r&&s)ICPY(AS(z),s,r); else *AS(z)=n;
 if(t&LAST0)*((I*)z+w-1)=0;
 R z;
}

static B jtsmmin(J jt,A a,A w){A*wv;I wd;MS*x;
 if(AFNJA&AFLAG(w))R a==w;
 x=(MS*)w-1;
 if((I)a==AABS(x,x->a))R 1;
 if(BOX&AT(w)){wv=AAV(w); wd=(I)w*ARELATIVE(w); DO(AN(w), if(smmin(a,WVR(i)))R 1;);}
 R 0;
}   /* 1 iff any leaf of w is part of SMM array a */

F2(jtsmmcar){A*wv,x,z;A1*zv;I n,t,wd;
 RZ(w);
 n=AN(w); t=AT(w); 
 ASSERT(t&B01+LIT+INT+FL+CMPX+BOX,EVDOMAIN);
 RZ(z=smmga(a,t,n,AR(w),AS(w)));
 zv=A1AV(z); wv=AAV(w);
 if(t&BOX){wd=(I)w*ARELATIVE(w); DO(n, RZ(x=smmcar(a,WVR(i))); zv[i]=AREL(x,z););}
 else MC(zv,wv,n*bp(t));
 R z;
}    /* make copy of w in SMM area of a */

F2(jtsmmis){A*wv,x;A1*av;I wd,wn,wr;
 RZ(a&&w);   
 if(a==w)R a;
 wn=AN(w); wr=AR(w);
 if(smmin(a,w))RZ(w=cpa(1,w));
 AK(a)=SZI*(AH+64); AT(a)=AT(w); AN(a)=wn; AR(a)=wr;
 if(!smminit(a)){AT(a)=LIT; AN(a)=0; AR(a)=1; *AS(a)=0; R 0;}
 av=A1AV(a); wv=AAV(w); wd=(I)w*ARELATIVE(w);
 DO(wn, x=smmcar(a,WVR(i)); if(!x){AT(a)=LIT; AN(a)=0; AR(a)=1; *AS(a)=0; R 0;} av[i]=AREL(x,a););
 ICPY(AS(a),AS(w),wr);
 R a;
}    /* a=:w where a is mapped and w is boxed */


A jtcpa(J jt,B b,A w){A*wv,z,*zv;I wd;
 if(0==b&&AFNJA&AFLAG(w))R ra(w);
 if(!(BOX&AT(w)))R ca(w);
 wv=AAV(w); wd=(I)w*ARELATIVE(w);
 GA(z,BOX,AN(w),AR(w),AS(w)); zv=AAV(z);
 DO(AN(w), RZ(zv[i]=cpa(b,WVR(i))););
 R z;
}    /* copy w down to leaves, recursing on boxed AFNJA iff 1=b */

static B leafrel(A w){A*v;
 if(BOX&AT(w)){
  if(AFLAG(w)&AFNJA)R 0;
  if(AFLAG(w)&AFSMM+AFREL)R 1;
  v=AAV(w); DO(AN(w), if(leafrel(v[i]))R 1;);
 }
 R 0;
}    /* 1 iff a leaf of w contains a relative address */

F1(jtrca){
 RZ(w);
 if(!(BOX&AT(w)))R AFSMM&AFLAG(w)?ca(w):w;
 R leafrel(w)?cpa(0,w):w;
}



static F1(jtsmmblkf){A z;I**mfree,p,q,*v,*zv;MS*x;
 RZ(w);
 mfree=SMMFREE(w);
 p=MLEN; q=0; 
 DO(p, v=mfree[i]; while(v){x=(MS*)AABS(v,w); ++q;                           v=x->a;});
 GA(z,INT,2*q,2,0); *AS(z)=q; *(1+AS(z))=2; zv=AV(z);
 DO(p, v=mfree[i]; while(v){x=(MS*)AABS(v,w); *zv++=(I)x; *zv++=msize[x->j]; v=x->a;});
 R z;
}    /* blocks free as a 2-column matrix of (address,size) */

static I smmblkun(B b,A w){A1*wv;I z=0;MS*x;
 x=(MS*)w-1;
 if(b&&x->a)z=1;
 if(BOX&AT(w)){wv=A1AV(w); DO(AN(w), z+=smmblkun(1,   (A)AABS(wv[i],w)););}
 R z;
}    /* # of lines in the result of smmblku */

static I* smmblku1(B b,I*zv,A w){A1*wv;MS*x;
 x=(MS*)w-1;
 if(b&&x->a){*zv++=(I)x; *zv++=msize[x->j];}
 if(BOX&AT(w)){wv=A1AV(w); DO(AN(w), zv=smmblku1(1,zv,(A)AABS(wv[i],w)););}
 R zv;
}

static A jtsmmblku(J jt,A w){A z;I n;
 RZ(w);
 n=smmblkun(0,w);
 GA(z,INT,2*n,2,0); *AS(z)=n; *(1+AS(z))=2;
 smmblku1(0,AV(z),w);
 R z;
}    /* blocks in use */

F1(jtsmmblks){A x,y,z;I n,t,*v,*zv;
 RZ(w);
 t=AT(w); 
 ASSERT(AFNJA&AFLAG(w)&&t&BOX,EVDOMAIN);
 RZ(x=smmblku(w));
 RZ(y=smmblkf(w));
 n=1+*AS(x)+*AS(y);
 GA(z,INT,3*n,2,0); *AS(z)=n; *(1+AS(z))=3; zv=AV(z); 
 *zv++=IMIN; *zv++=IMIN; *zv++=IMIN;
 v=AV(x); DO(*AS(x), *zv++=*v++; *zv++=*v++; *zv++=SMMCINUSE;);
 v=AV(y); DO(*AS(y), *zv++=*v++; *zv++=*v++; *zv++=SMMCFREE; );
 RZ(z=grade2(z,z)); zv=AV(z);
 *zv++=(I)smmu(w); *zv++=smmsize(w); *zv++=SMMCTOTAL;
 R z;
}    /* 15!:12 all the blocks in an SMM variable as 3-column matrix */

/*
// F2(jtafr2){A x,*wv;A1*wu;
//  RZ(a&&w);
//  wv=AAV(w); wu=A1AV(w);
//  DO(AN(w), x=(A)AABS(wu[i],a); if(BOX&AT(x))RZ(x=afr2(a,x)); wv[i]=x;);
//  R w;
// }    /* w has addresses relative to a; works in place */

A relocate(I m,A w){A1*wv; RZ(w); AFLAG(w)|=AFREL; wv=A1AV(w); DO(AN(w), wv[i]+=m;); R w;}
     /* add m to the addresses in w; works in place */