diff --git a/jsrc/af.c b/jsrc/af.c index 84b64253d..519c332a3 100644 --- a/jsrc/af.c +++ b/jsrc/af.c @@ -44,8 +44,7 @@ B jthasimploc(J jt,A w){A hs,*u;V*v; if(AT(thisname)&NOUN)R 0; // if noun~, leave as is NM* thisnameinfo=NAV(thisname); // the NM block for the current name if(!(thisnameinfo->flag&NMIMPLOC))R 0; // not u./v. - // obsolete if(!(jtprobe((J)((I)jt+NAV(thisname)->m),NAV(thisname)->s,NAV(thisname)->hash,jt->locsyms)))R 0; // assigned value does not exist - if(!probex(NAV(thisname)->m,NAV(thisname)->s,SYMORIGIN,NAV(thisname)->hash,jt->locsyms))R 0; // assigned value does not exist + if(!probex(NAV(thisname)->m,NAV(thisname)->s,SYMORIGIN,NAV(thisname)->hash,jt->locsyms))R 0; // assigned value does not exist R 1; case CATDOT: case CGRCO: @@ -135,8 +134,7 @@ static A jtfixa(J jt,A a,A w){A f,g,h,wf,x,y,z=w;V*v;fauxblock(fauxself); A aa; if(thisname){ // name given NM* thisnameinfo=NAV(thisname); // the NM block for the current name if(thisnameinfo->flag&NMIMPLOC){ // implicit locative - // obsolete if((jtprobe((J)((I)jt+NAV(thisname)->m),NAV(thisname)->s,NAV(thisname)->hash,jt->locsyms))){ // name is defined - if(probex(NAV(thisname)->m,NAV(thisname)->s,SYMORIGIN,NAV(thisname)->hash,jt->locsyms)){ // name is defined + if(probex(NAV(thisname)->m,NAV(thisname)->s,SYMORIGIN,NAV(thisname)->hash,jt->locsyms)){ // name is defined // If our ONLY mission is to replace implicit locatives, we are finished after replacing this locative IF // (1) we want to replace only first-level locatives; (2) there are no more locatives in this branch after the replacement if(aif&FIXALOCSONLYLOWEST)R x; // return looked-up value once we hit one diff --git a/jsrc/am.c b/jsrc/am.c index 552bbfe97..47cf0efdc 100644 --- a/jsrc/am.c +++ b/jsrc/am.c @@ -80,7 +80,6 @@ F1(jtcasev){A b,*u,*v,w1,x,y,z;B*bv,p,q;I*aa,c,*iv,j,m,n,r,*s,t; // fast (no-error) case; and of course if the use-count is only 2 (incremented by the call to symbrd from 1). But if the assignment is local, we also have to make // sure abc is locally defined if(p=q&&0<=c&&AC(u[c])<=ACUC2&&!(AFLAG(u[c])&AFRO)) { // passes quick check: 2-name fast case, reassigned name, modifiable usecount, not read-only -// obsolete p= (!EXPLICITRUNNING) || CAV(QCWORD(AAV(v[m+2])[1]))[0]!=CASGN || jtprobe((J)((I)jt+NAV(QCWORD(AAV(v[m+2])[0]))->m),NAV(QCWORD(AAV(v[m+2])[0]))->s,NAV(QCWORD(AAV(v[m+2])[0]))->hash, jt->locsyms); // OK if not in explicit, or not local assignment, or name defined p= (!EXPLICITRUNNING) || CAV(QCWORD(AAV(v[m+2])[1]))[0]!=CASGN || probex(NAV(QCWORD(AAV(v[m+2])[0]))->m,NAV(QCWORD(AAV(v[m+2])[0]))->s,SYMORIGIN,NAV(QCWORD(AAV(v[m+2])[0]))->hash, jt->locsyms); // OK if not in explicit, or not local assignment, or name defined // Get the pointer to the parsed sentence; go to its data; take pointer for word[1]; go to its (character) data; take first character // then look up the symbol entry for word[0] diff --git a/jsrc/ar.c b/jsrc/ar.c index 2f5a44ec4..e27a4420d 100644 --- a/jsrc/ar.c +++ b/jsrc/ar.c @@ -592,7 +592,6 @@ static A jtredsp1(J jt,A w,A self,C id,VARPSF ado,I cv,I f,I r,I zt){A e,x,z;I m DF1(jtredravel){A f,x,z;I n;P*wp; F1PREFIP;PROLOG(0000); -// obsolete if(likely(!ISSPARSE(AT(w)))){RZ(z=reduce(jtravel(jtinplace,w),f)); if(likely(!ISSPARSE(AT(w)))){RZ(z=on1cell(jtinplace,w,self)); // reversion is the normal path }else{ ARGCHK1(w); diff --git a/jsrc/ca.c b/jsrc/ca.c index 17bf3acaa..ba77801c6 100644 --- a/jsrc/ca.c +++ b/jsrc/ca.c @@ -162,7 +162,6 @@ static DF2(jtmodpow2){A h;B b,c;I m,n,x,z; if(unlikely(((AT(a)|AT(w))&(NOUN&~(INT+XNUM)))!=0)){ // convert any non-INT arg to INT if it can be done exactly if(RAT&AT(a))RZ(a=pcvt(XNUM,a)) else if(!(AT(a)&INT+XNUM))RZ(a=pcvt(INT,a)); if(RAT&AT(w))RZ(w=pcvt(XNUM,w)) else if(!(AT(w)&INT+XNUM))RZ(w=pcvt(INT,w)); -// obsolete if(((AT(a)|AT(w))&(NOUN&~(INT+XNUM)))!=0)R residue(h,expn2(a,w)); // if not (both args INT and power positive) revert to long form if(((AT(a)|AT(w))&(NOUN&~(INT+XNUM)))!=0)R jtupon2(jt,a,w,self); // if not (both args INT and power positive) revert to long form } // both args are integral, but possibly extended diff --git a/jsrc/cf.c b/jsrc/cf.c index c57fb343c..19599936b 100644 --- a/jsrc/cf.c +++ b/jsrc/cf.c @@ -216,12 +216,10 @@ static DF1(jthkiota){A a,e;I n;P*p; SETIC(w,n); if(unlikely((AT(w)&SPARSE+B01)==SPARSE+B01)&&1==AR(w)){ // sparse boolean list p=PAV(w); a=SPA(p,a); e=SPA(p,e); -// obsolete R BAV(e)[0]||equ(mtv,a) ? repeat(w,IX(n)) if(BAV(e)[0]||equ(mtv,a))goto revert; // revert if no sparse axes or fill ele is not 0 R repeat(SPA(p,x),ravel(SPA(p,i))); // select from the indexes (of nonzeros) } if(B01&AT(w)&&1>=AR(w))R ifb(n,BAV(w)); // use special code for boolean atom/list -// obsolete : repeat(w,IX(n)); revert: ; R jthook1cell(jt,w,self); } /* special code for (# i.@#) y */ @@ -234,7 +232,6 @@ static DF1(jthkodom){I n,*v; } revert: ; R jthook1cell(jt,w,self); -// obsolete R CALL2(FAV(fs)->valencefns[1],w,CALL1(FAV(gs)->valencefns[0],w,gs),fs); } /* special code for (#: i.@(* /)) */ static DF1(jthkindexofmaxmin){ diff --git a/jsrc/cx.c b/jsrc/cx.c index 631357c83..88f77222e 100644 --- a/jsrc/cx.c +++ b/jsrc/cx.c @@ -466,7 +466,6 @@ nextlinedebug:; // Check for assert. Since this is only for T-blocks we tolerate the test (rather than duplicating code) if(unlikely(TEQ5(tcesx,CASSERT))){ if(JT(jt,assert)){ -// obsolete parseline(t,{if(likely((tcesx&((UI8)TCESXCECANT<<32))!=0))tpop(old);else z=gc(z,old);},); if(t&&!(NOUN&AT(t)&&all1(eq(num(1),t))))t=pee(cwsent,CWTCESX2(cwsent,ic),EVASSERT,NPGpysfmtdl<<(BW-2),jt->sitop->dclnk); // if assert., signal post-execution error if result not all 1s. parseline(t,{if((UI)jt->tnextpushp-(UI)old>TPOPSLACK*SZI)if(likely((tcesx&((UI8)TCESXCECANT<<32))!=0))tpop(old);else z=gc(z,old);},); if(t&&!(NOUN&AT(t)&&all1(eq(num(1),t))))t=pee(cwsent,CWTCESX2(cwsent,ic),EVASSERT,NPGpysfmtdl<<(BW-2)); // if assert., signal post-execution error if result not all 1s. if(likely(t!=0)){ // assert without error diff --git a/jsrc/d.c b/jsrc/d.c index 23c6dac40..4445df92f 100644 --- a/jsrc/d.c +++ b/jsrc/d.c @@ -238,8 +238,6 @@ A jteformat(J jt,A self,A a,A w,A m){ // we have to reset the state of the error system after saving what we will need I pareninfo = (jt->emsgstate&EMSGSTATEPAREN)>>EMSGSTATEPARENX; // unbalanced-paren info from infererrtok RESETERR; jt->emsgstate|=EMSGSTATEFORMATTED; // clear error system; indicate that we are starting to format, so that the error line will not be modified during eformat -// obsolete A nam=nfs(10,"eformat_j_"); A val; if((val=syrd(nam,jt->locsyms))==0)goto noeformat; if((val=QCWORD(namerefacv(nam,val)))==0)goto noeformat; -// obsolete if(!(val&&LOWESTBIT(AT(val))&VERB))goto noeformat; // there is always a ref, but it may be to [:. Undo ra() in syrd A nam=nfs(10,"eformat_j_"); A val; if((val=syrd(nam,jt->locsyms))==0)goto noeformat; if((val=QCWORD(namerefacv(nam,QCWORD(val))))==0)goto noeformat; if(!(val&&LOWESTBIT(AT(val))&VERB))goto noeformat; // there is always a ref, but it may be to [:. namerefscv will undo ra() in syrd // we also have to reset processing state: ranks. It seems too hard to force eformat to infer the ranks from the args diff --git a/jsrc/io.c b/jsrc/io.c index b44495788..8734d55d6 100644 --- a/jsrc/io.c +++ b/jsrc/io.c @@ -341,7 +341,6 @@ void breakclose(JS jt); // result is NUL-terminated string which is on the tstack // We echo the string before returning static C* nfeinput(JS jt,C* s){A y; -// obsolete WITHATTNDISABLED(y=jtstr0(MDTHREAD(jt),jtexec1(MDTHREAD(jt),jtcstr(MDTHREAD(jt),s),ds(CEXEC)));) // exec the sentence with break interrupts disabled to get the string; NUL-terminate WITHATTNDISABLED(y=jtstr0(MDTHREAD(jt),PARSERVALUE(jtparse((JTT*)((I)MDTHREAD(jt)|JTFROMEXEC),jtddtokens(MDTHREAD(jt),jtcstr(MDTHREAD(jt),s),4+1+0))));); // replace DDs, but require that they be complete within the string (no jgets); 0 is !!EXPLICITRUNNING; execute, NUL-terminate if(!y){breakclose(jt);exit(2);} /* J input verb failed */ diff --git a/jsrc/j.h b/jsrc/j.h index 4c66b22e0..b6e0f0759 100644 --- a/jsrc/j.h +++ b/jsrc/j.h @@ -1015,7 +1015,6 @@ struct jtimespec jmtfclk(void); //'fast clock'; maybe less inaccurate; intended #define BLOOMSET(b,c) ((b)[(c)>>LGBB]|=(1<<((c)&BB-1))) // set Bloom bit c in b. Requires write lock on the locale #define BLOOMCLEAR(l) mvc(BLOOMLEN(l),BLOOMBASE(l),MEMSET00LEN,MEMSET00) // reset Bloom filter to 0s #define BLOOMFILL(l) {((LX*)BLOOMBASE(l))[0]=-1; if(unlikely((UI)AN(l)>sizeof(LX)*BB))memset(BLOOMBASE(l),0xff,BLOOMLEN(l));} // reset Bloom filter to 1s (for local table) - usually with 1 store (if <=32 chains) -// obsolete #define BLOOMMASK(hash) ((0x1LL<<((hash)&(BW-1)))) // Bloom filter for a given hash #define BMK(x) (1LL<<(x)) // bit number x // test for equality of 2 8-bit values simultaneously #define BOTHASUS(x,y) (((US)(C)(x)<<8)+(US)(C)(y)) diff --git a/jsrc/je.h b/jsrc/je.h index 2a480e194..9631776ea 100644 --- a/jsrc/je.h +++ b/jsrc/je.h @@ -856,7 +856,6 @@ extern B jtpreparse(J,A,A*,A*); extern B jtprimitive(J,A); extern A probe(I,C*,L *,UI8); extern B jtprobedel(J,C*,UI4,A); -// obsolete extern L* jtprobeis(J, A, A); extern L* jtprobeisres(J, A, A); extern L* jtprobeislocal(J,A,A); extern A jtprobequiet(J, A); diff --git a/jsrc/jtype.h b/jsrc/jtype.h index ac1ae5d06..8e1eac6c5 100644 --- a/jsrc/jtype.h +++ b/jsrc/jtype.h @@ -195,7 +195,6 @@ struct AD { union { I m; // Multi-use field. (1) For NJA/SMM blocks, size of allocation. (2) in syncos, a credential to allow pthread calls // (3) for SYMB tables for explicit definitions (i. e. local SYMB tables), the address of the calling symbol table; -// obsolete for other SYMB tables, a Bloom filter of the hashes assigned in the locale (using the low bits of the hash) // (4) for the block holding the amend offsets in x u} y, the number of axes of y that are built into the indexes in u // (5) in the return from wordil, holds the number of words if any final NB. is discarded; (6) in the result of indexofsub when called for FORKEY, contains the // number of partitions found; (7) in the self block for y L: n and u S: n, the address of the fs block for u; (8) in the call to jtisf (multiple assignment), holds the @@ -658,7 +657,6 @@ struct AD { #define ACSETPERM(x) {AC(x)=ACPERMANENT+100000; __atomic_fetch_or(&AFLAG(x),(AT(x)&RECURSIBLE),__ATOMIC_ACQ_REL);} // Make a block permanent from now on. In case other threads have committed to changing the usecount, make it permanent with a margin of safety #define SGNIFPRISTINABLE(c) ((c)+ACPERMANENT) // sign is set if this block is OK in a PRISTINE boxed noun // s is an expression that is neg if it's OK to inplace -// obsolete #define ASGNINPLACENEG(s,w) ((s)&(AC(w)|SGNIF(jt->zombieval==w,0))) // neg if OK to inplace ordinary operation, either because the block is inplaceable or because it's an assignment to zombie #if SY_64 // Note: the following will fail if bit 63 of address may differ between jt->zombieval and w. That will not be in my lifetime. When it happens, perhaps clang will have fixed the version above not to create a branch #define ASGNINPLACENEG(s,w) ((s)&(AC(w)|(((I)jt->zombieval^(I)w)-1))) // neg if OK to inplace ordinary operation, either because the block is inplaceable or because it's an assignment to zombie @@ -897,11 +895,6 @@ typedef DST* DC; #define VALTYPENAMELESS ((SYMBX-LASTNOUNX)+1) // 6 set in nameless non-locative ACV, to suppress reference creation. #define VALTYPESPARSE ((CONWX-LASTNOUNX)+1) // 7 set in sparse noun, which is the only type of a stored value that requires traverse. Has bit 0 set, as befits a noun #define NAMELESSQCTOTYPEDQC(q) q=(A)(((I)q&~0xf)+ATYPETOVALTYPEACV(AT(QCWORD(q)))); // q is name of NAMELESS QC; result has QC type for AT(q) with unchanged semantics -// obsolete // scaf remove the following -// obsolete #define QCGLOBALX 5 -// obsolete #define QCGLOBAL ((I)1<kchain.locpath // the path, allocated with rank 1 (so the path is in one cacheline). If 0, the locale has been deleted. The path runs from LOCPATH backwards // to end with the ending 0 at AAV1()[0] -// obsolete #define LOCBLOOM(x) AM(x) -// obsolete #define BLOOMOR(x,v) {LOCBLOOM(x)|=(v);} // or a new value into the Bloom filter. MUST be done under lock // Macros to incr/decr execct of a locale @@ -1374,7 +1364,6 @@ typedef struct __attribute__((aligned(CACHELINESIZE))) {I memhdr[AKXR(0)/SZI]; u #define MEMSET00LEN (4*SZI) // length of MEMSET00 #define MEMSETFF ((C*)(validitymask+8)) // 2 words of FF, for memset (only 2 in 32-bit systems) #define MEMSETFFLEN (2*SZI) // length of MEMSETFF -// obsolete #define MEMSETFF ((C*)(iotavec-IOTAVECBEGIN+0xff)) // 1 byte of 0xff, for memset #define MEMSET01 ((C*)(iotavec-IOTAVECBEGIN+1)) // 1 byte of 0x01, for memset diff --git a/jsrc/m.c b/jsrc/m.c index 50e7180eb..f227c03e7 100644 --- a/jsrc/m.c +++ b/jsrc/m.c @@ -966,7 +966,6 @@ if(np&&AC(np)<0)SEGFAULT; // contents are never inplaceable // If it is a nameref, clear the bucket info. Explanation in nameref() if(unlikely(v->id==CTILDE))if(v->fgh[0]&&AT(v->fgh[0])&NAME)NAV(v->fgh[0])->bucket=0; // Recur on each component -// obsolete raonlys(v->fgh[0]); raonlys(v->fgh[1]); raonlys(v->fgh[2]); DO(3, if(v->fgh[i])ra(v->fgh[i]);) // ra f, g, h } else if(t&(RAT|XNUM|XD)) {A* RESTRICT v=AAV(wd); // single-level indirect forms. handle each block @@ -1023,7 +1022,6 @@ runout:; // } } else if(t&(VERB|ADV|CONJ)){V* RESTRICT v=FAV(wd); // ACV. -// obsolete fana(v->fgh[0]); fana(v->fgh[1]); fana(v->fgh[2]); DO(3, fana(v->fgh[i]);) // free f, g, h } else if(t&NAME){A ref; // NAMEs are usually in verb defns and don't get freed if((ref=QCWORD(NAV(wd)->cachedref))!=0 && !(ACISPERM(ref))){I rc; // reference, and not permanent, which means not to a nameless adv. must be to a ~ reference diff --git a/jsrc/p.c b/jsrc/p.c index 27a82f4be..e1dd1fb63 100644 --- a/jsrc/p.c +++ b/jsrc/p.c @@ -470,7 +470,6 @@ void protectlocals(J jt, I ofst){PSTK *stk=jt->parserstackframe.parserstkend1; A A jtparsea(J jt, A *queue, I nwds){F1PREFIP;PSTK *stack;A z,*v; // whenever we execute a fragment, parserstkend1 must be set to the execution stack of the fragement; the stack will be analyzed // to get the error token. Errors during the stacking phase will be located from this routine -// obsolete if((I)JT(jt,jobqueues)&63)SEGFAULT; if(likely(nwds>1)) { // normal case where there is a fragment to parse // Save info for error typeout. We save pointers to the sentence, and the executing parser-stack frame for each execution, from which we infer error position PFRAME oframe=jt->parserstackframe; // save all the stack status @@ -526,7 +525,6 @@ A jtparsea(J jt, A *queue, I nwds){F1PREFIP;PSTK *stack;A z,*v; #define ASGNEDGE ((0xfLL<>QCTYPE(queue[-1])) & (~((0xfLL<>QCTYPE(queue[-2])))&1; // NOTE: if nwds<3 (must be 2 then) this will fetch 1 word from before the beginning I pull4=((~(UI8)ASGNEDGE>>QCTYPE(queue[-1])) & (~(UI8)ASGNEDGE>>QCTYPE(queue[-2])))&1; // NOTE: if nwds<3 (must be 2 then) this will fetch 1 word from before the beginning // of queue. That's OK, because the fetch will always be legal, as the data always has a word of legal data (usually the block header; in pppp an explicit pad word) @@ -564,7 +562,6 @@ A jtparsea(J jt, A *queue, I nwds){F1PREFIP;PSTK *stack;A z,*v; // We have the value/typeclass of the next word (QCSENTENCE semantics). If it is an unassigned name, we have to resolve it and perhaps use the new name/type if(((I)y&QCISLKPNAME)){ -// obsolete if((I)y&QCNAMED+QCISLKPNAME)SEGFAULT; y=CLRQCFAOWEDMSK(y); // y is now addr/00/type index // Replace a name (not to left of ASGN) with its value // Name, not being assigned // Resolve the name. If the name is x. m. u. etc, always resolve the name to its current value; @@ -582,7 +579,6 @@ A jtparsea(J jt, A *queue, I nwds){F1PREFIP;PSTK *stack;A z,*v; // this is the path for all local names as long as we can use the uncloned table L *s=sympv+(I)symx; // get address of symbol from the primary table if(unlikely((s->fval)==0))goto rdglob; // if value has not been assigned, ignore it. y has QCSYMVAL semantics -// obsolete y=(A)((I)s->val+s->valtype); // combine the type and value. type has QCSYMVAL semantics, as y does. if(unlikely(ISRAREQD(y=s->fval)))raposlocalqcgsv(QCWORD(y),QCPTYPE(y),y); // ra the block if needed - rare for locals (only sparse). Now we call it QCFAOWED semantics }else if(likely((buck=NAV(QCWORD(y))->bucket)>0)){ // buckets but no symbol - must be global, or recursive symtab - but not synthetic new name. We would fetch symx&buck together if we could hand-code it. // public names come through here (with positive pucketx) or @@ -637,7 +633,6 @@ rdglob: ; // here when we tried the buckets and failed #endif FPSZSUFF(y=nameundco(jtinplace, QCWORD(*(volatile A*)queue), y), fa(QCWORD(y));) }else y=SYMVALTOFAOWED(y) ; // if global, mark to free later -// obsolete if(!((I)y&QCNAMED))SEGFAULT; y=SETNAMED(y); }else if(unlikely(QCPTYPE(y)==VALTYPENAMELESS)){ // nameless modifier, and not a locative. This handles 'each' and the like. Don't create a reference; maybe cache the value A origy=QCWORD(*(volatile A*)queue); // refetch name so we can look at its flags @@ -647,15 +642,12 @@ rdglob: ; // here when we tried the buckets and failed // cachable and not a locative (and not a noun). store the value in the name, make the value permanent NAV(origy)->cachedref=CLRFAOWED(y); NAV(origy)->bucket=0; ACSETPERM(QCWORD(y)); // clear bucket info so we will skip that search - this name is forever cached with QCFAOWED semantics. Make the cached value immortal } -// obsolete if(!((I)y&QCNAMED))SEGFAULT; y=SETNAMED(y); -// obsolete y=SETFAOWED(y); }else{ // not a noun/nonlocative-nameless-modifier. We have to stack a reference to the ACV. But if the value IS a reference, use the value if possible to avoid the extra lookup A origname=QCWORD(*(volatile A*)queue); // refetch the name #if 0 // obsolete if it's to be done, it should be in unquote if(unlikely(FAV(QCWORD(y))->valencefns[0]==jtunquote && !(NAV(origname)->flag&(NMLOC|NMILOC|NMIMPLOC)))){ // reference is as reference does // the value is a non-locative reference to another reference. It is safe to skip over it. Leave y holding the value y=SYMVALTOFAOWED(y) ; // if global, mark to free later -// obsolete y=SETFAOWED(y); // convert to QCFAOWED semantics }else{y=namerefacv(origname,y);} // Replace other acv with reference, and fa() looked-up y value if global. y starts with QCGLOBAL semantics, returns with QCFAOWED #endif y=namerefacv(origname,y); // Replace acv with reference, and fa() looked-up y value if global. y starts with QCFAOWED semantics, returns with QCFAOWED @@ -669,7 +661,6 @@ rdglob: ; // here when we tried the buckets and failed FPSZ(y) // abort if failure allocating reference, or malformed name } endname: ; -// obsolete y=SETNAMED(y); // turn on the flag bit indicating this was NAMED // else // not a name requiring lookup. enqueue() set the QC flags, which we will use below. We have just checked the NAMED flag, off here. Now we notionally switch to // QCFAOWED semantics, in which QCISLKPNAME is repurposed to QCFAOWED (& known to be 0). enqueue() sets QCNAMED+~FAOWED in blocks that are known to need no pretection from deletion: @@ -689,7 +680,6 @@ endname: ; --pt0ecam; // decrement token# for the word we just processed queue--; // OK to fetch queue[-1] // stack the value, changing it to STKNAMED semantics -// obsolete stack[0].a = (A)(((I)y&~STKFAOWED)+(((I)y>>(QCFAOWEDX-STKFAOWEDX))&STKFAOWED)); // finish setting the stack entry, with the new word. The stack entry has STKNAMED/STKFAOWED with garbage in other type flags stack[0].a = (A)(((I)y&~QCMASK)+(((I)y>>(QCNAMEDX-STKNAMEDX))&STKNAMEDMSK)); // finish setting the stack entry, with the new word. The stack entry has STKNAMED/STKFAOWED with the rest of the address valid (no type flags) y=*(volatile A*)queue; // fetch next value as early as possible pt0ecam|=((1LL<<(LASTNOUNX-1))<>QCADV)|(CONJ>>QCVERB)|(CONJ>>QCNOUN)|(CONJ>>QCISLKPNAME)|(CONJ>>(QCISLKPNAME+QCNAMEBYVALUE))|(CONJ>>(QCISLKPNAME+QCNAMEBYVALUE+QCNAMEABANDON))) -// obsolete <<(QCTYPE(y)))&CONJ; // save next-is-CAVN status in CONJ (which will become the request for a 2nd pull). pt0ecam|=(((((UI8)1<>(QCTYPE(y)))&(UI8)1)<>((pt0ecam>>PMASKSAVEX)&1))); // pointer to stack slot that was executed 1 2 2 (2 2) -// obsolete PSTK *fsa2=(PSTK*)((I)stack+((2*sizeof(PSTK))>>((pt0ecam>>PMASKSAVEX)&1))); // pointer to stack slot that was executed 1 2 2 (2 2) -// obsolete freep=fsa2->a; freepc=__atomic_load_n(&AC(QCWORD(freep)),__ATOMIC_RELAXED); freept=__atomic_load_n(&AT(QCWORD(freep)),__ATOMIC_RELAXED); PSTK *fsa2=&stack[2+((pt0ecam&((I)1<>(freea==y); // get inplaceability; set off if the arg is the result I zapok=(AC(freea)&(-(AT(freea)&DIRECT)|SGNIF(AFLAG(freea),AFPRISTINEX))); zapok=freea==y?0:zapok; // (not return value) and abandoned. Sparse blocks are never abandoned if(zapok<0){INCRSTAT(wpopfa/*0.45*/) *tpopw=0; fanapop(freea,AFLAG(freea)); // zap the top block; if recursive, fa the contents. We free tpopw before subroutine }else{INCRSTAT(wpopnull/*0.55*/)} -// obsolete }else{INCRSTAT(wpopnull/*0.55*/) } }else{INCRSTAT(wnull/*.01*/)} } // repeat for a if any -// obsolete freea=__atomic_load_n((A*)((I)tpopa&-SZI),__ATOMIC_RELAXED); -// obsolete freep=(A)QCWORD(tpopa); freep=ISSTKNAMED(tpopa)?freep:(A)jt; -// obsolete freepc=__atomic_load_n(&AC(freep),__ATOMIC_RELAXED); freept=__atomic_load_n(&AT(freep),__ATOMIC_RELAXED); -// obsolete if(ISSTKNAMED(tpopa)){INCRSTAT(afaowed/*.36*/) if(unlikely(freep==y)){INCRSTAT(afainh/*.02*/) y=(A)tpopa;}else{INCRSTAT(afafa/*.98*/) faifowed(freep,freepc,freept,tpopa);}} if(ISSTKNAMED(tpopa)){INCRSTAT(afaowed/*.8*/) if(unlikely((A)QCWORD(tpopa)==y)){INCRSTAT(afainh/*.02*/) y=(A)tpopa;}else if(withprob(ISSTKFAOWED(tpopa),0.2)){INCRSTAT(wfafa/*.98*/) faowed((A)QCWORD(tpopa),AC((A)QCWORD(tpopa)),AT((A)QCWORD(tpopa)));}} else{ /*.2*/ -// obsolete A freeav=freea=*(A*)((I)tpopa&-SZI); freeav=freeav?freeav:(A)jt; // make freea valid for reading from -// obsolete A freeav=freea; freeav=freeav?freeav:(A)jt; // make freea valid for reading from -// obsolete I freeac=__atomic_load_n(&AC(freeav),__ATOMIC_RELAXED); I freeat=__atomic_load_n(&AT(freeav),__ATOMIC_RELAXED); I freeaflag=__atomic_load_n(&AFLAG(freeav),__ATOMIC_RELAXED); -// obsolete if(unlikely(freea!=0)){INCRSTAT(apop/*.20*/) // if freea==arg2 this will never load a value requiring action -// obsolete I c=(UI)freeac>>(freea==y); -// obsolete if((c&(-(freeat&DIRECT)|SGNIF(freeaflag,AFPRISTINEX)))<0){INCRSTAT(apopfa/*0.30 local, 0.06 global*/) // abandoned, not return value, not same as freea, dyad. Safe to check AC even if freed as freea -// obsolete *tpopa=0; if(freeaflag&RECURSIBLE)INCRSTAT(apoprecur); fanapop(freea,freeaflag); -// obsolete }else{INCRSTAT(apopnull/*0.70 local, 0.15 global*/)} -// obsolete }else{INCRSTAT(anull/*.25*/)} freea=*tpopa; // get the tstack pointer, which points back to the arg if it has not been zapped if(likely(freea!=0)){INCRSTAT(apop/*.95*/) // if the arg has a place on the tstack, look at it to see if the block is still around -// obsolete if(((I)((UI)AC(freea)>>(freea==y))&(-(AT(freea)&DIRECT)|SGNIF(AFLAG(freea),AFPRISTINEX)))<0){INCRSTAT(apopfa/*0.4*/) // (not return value) and abandoned. Sparse blocks are never abandoned -// obsolete *tpopa=0; if(AFLAG(freea)&RECURSIBLE)INCRSTAT(apoprecur/*.01*/); fanapop(freea,AFLAG(freea)); // zap the top block; if recursive, fa the contents. We free tpopa before subroutine I zapok=(AC(freea)&(-(AT(freea)&DIRECT)|SGNIF(AFLAG(freea),AFPRISTINEX))); zapok=freea==y?0:zapok; // (not return value) and abandoned. Sparse blocks are never abandoned if(zapok<0){INCRSTAT(apopfa/*0.4*/) *tpopa=0; fanapop(freea,AFLAG(freea)); // zap the top block; if recursive, fa the contents. We free tpopa before subroutine }else{INCRSTAT(apopnull/*0.6*/)} @@ -917,7 +877,6 @@ RECURSIVERESULTSCHECK stack[1].a=y; // save result 2 3 3; parsetype (noun) is unchanged, token# is immaterial y=NEXTY; // refetch next-word to save regs fsa2=stack-1; stack=(pt0ecam&(2<val=0 to ensure flags=0 in return value - }else{y=QCWORD(namerefacv(y, sv));} // Replace other acv with reference. Could fail. Flags in sv=s->val=0 to prevent fa() and ensure flags=0 in return value + }else{y=QCWORD(namerefacv(y, sv));} // Replace other acv with reference. Could fail. Flags in sv=s->val=0 to prevent fa() and ensure flags=0 in return value goto gotlocalval; // y has the unprotected value read. We can use that. } } @@ -1185,13 +1125,10 @@ abandname:; // The name was found, not in a static local table. sv has QCFAOWED semantics if(likely((I)sv&QCNOUN)||unlikely(yflags&QCNAMEBYVALUE)){ // if noun or special name, use value if(unlikely(yflags&QCNAMEABANDON)){ -// obsolete #if !LOCALRA // If the value is local, we must ra it because undco() expects it (questionable) if(unlikely(!ISRAREQD(sv)))rapos(QCWORD(sv),sv); // ra() the new value first -// obsolete #endif sv=nameundco(jtinplace, y, sv); // if name_:, go delete the name, leaving the value to be deleted later. returned sv has QCFAOWED semantics y=QCWORD(sv); sv=(A)ISFAOWED(sv); // undco will set FAOWED if it didn't fa() the value; transfer that to sv -// obsolete }else{y=QCWORD(sv); if(!LOCALRA)sv=(A)ISGLOBAL(sv);} // not name_:, just use the value. sv=non0 if it needs free }else{y=QCWORD(sv); sv=(A)ISFAOWED(sv);} // not name_:, just use the value. sv=non0 if it needs free }else{y=QCWORD(namerefacv(y, sv)); sv=0;} // Replace other acv with reference. Could fail. Undo the ra from syrd if global, so clear sv to indicate no further fa }else{ @@ -1205,8 +1142,6 @@ abandname:; // If sv!=0, we found the value and ra()d it. Match the ra with a tpush so that the value stays protected during further execution if(likely(sv!=0)){if(likely(y!=0)){tpush(y);}else fa(sv);} // undo the ra() in syrd. In case someone else deletes the value, protect it on the tpop stack till it can be displayed } // any single-word sentence from enqueue must be a name or a CAVN -// obsolete else if(unlikely(!(AT(y)&CAVN))){jsignal(EVSYNTAX); y=0;} // not a name - might be something like =. - if not CAVN, error -// obsolete if(likely(y!=0)) }else y=mark; // empty input - return with 'mark' as the value, which means nothing to parse. This result must not be passed into a sentence gotlocalval:; // local fetches can skip the tpush. Value in y R y; // indicate not a final assignment - and may be 0 diff --git a/jsrc/s.c b/jsrc/s.c index 7d8910424..24a6a8b96 100644 --- a/jsrc/s.c +++ b/jsrc/s.c @@ -35,7 +35,6 @@ // to the local table in the calling explicit definition // // within named/numbered locales, AK points to the path (a list of boxes, using AAV0, pointing to the SYMB blocks of the path) -// obsolete // and AM is the Bloom filter for the locale. #define symcol ((sizeof(L)+SZI-1)/SZI) @@ -270,12 +269,8 @@ B jtprobedel(J jt,C*string,UI4 hash,A g){B ret; // l/string are length/addr of name, hash is hash of the name, g is symbol table. l is encoded in low bits of jt // result is addr/ra/flags for value (i. e. QCSYMVAL semantics), or 0 if not found // locking is the responsibility of the caller -// obsolete A jtprobe(J jt,C*string,UI4 hash,A g){ -// obsolete RZ(g); A probe(I len, C *string, L *sympv, UI8 hashsymx){ LX symx=(LX)hashsymx; UI4 hash=hashsymx>>32; // extract args from composite arg. symx may have be flagged -// obsolete LX symx=LXAV0(g)[SYMHASH(hash,AN(g)-SYMLINFOSIZE)]; // get index of start of chain -// obsolete L *sympv=SYMORIGIN; // base of symbol table L *symnext, *sym=sympv+SYMNEXT(symx); // first symbol address - might be the free root if symx is 0 NOUNROLL while(symx){ // loop is unrolled 1 time // sym is the symbol to process, symx is its index. Start by reading next in chain. One overread is OK, will be symbol 0 (the root of the freequeue) @@ -323,7 +318,6 @@ A jtprobelocal(J jt,A a,A locsyms){NM*u;I b,bx; R probelocalbuckets(SYMORIGIN,a,LXAV0(locsyms)[b],u->bucketx); // look up using bucket info }else{ // No bucket information, do full search. This includes names that don't come straight from words in an explicit definition -// obsolete R jtprobe((J)((I)jt+NAV(a)->m),NAV(a)->s,NAV(a)->hash,locsyms); R probex(NAV(a)->m,NAV(a)->s,SYMORIGIN,NAV(a)->hash,locsyms); } } @@ -399,7 +393,6 @@ L *jtprobeislocal(J jt,A a,A lsym){NM*u;I bx;L *sympv=SYMORIGIN; // No bucket information, do full search. We do have to reserve a symbol in case the name is new // We don't need a lock, because this is a local table; but this path is rare - only for computed names, and for assignments // during creation of the local symbol tables, where we will keep the lock once we take it -// obsolete SYMRESERVE(1) L *l=probeis(a,lsym); WRITEUNLOCK(lsym->lock); // release the unneeded lock L *l=probeisres(a,lsym); RZ(l); // search for name, then release lock AR(lsym)|=((~l->flag)&LPERMANENT)<<(ARNAMEADDEDX-LPERMANENTX); // Mark that a name has been added beyond what was known at preprocessing time, if the added name is not PERMANENT R l; @@ -416,18 +409,14 @@ L *jtprobeislocal(J jt,A a,A lsym){NM*u;I bx;L *sympv=SYMORIGIN; A jtsyrd1(J jt,C *string,UI4 hash,A g){A*v,x,y; RZ(g); F1PREFIP; // make sure there is a locale... // we store an extra 0 at the end of the path to allow us to unroll this loop once -// obsolete I bloom=BLOOMMASK(hash);Bloom for input block; v=LOCPATH(g); L *sympv=SYMORIGIN; // v->|.locales, with NUL at font; sympv doesn't change here // This function is called after local symbols have been found wanting. Usually g will be the base // of the implied path. But if the value is a locative, g is the locative locale to start in, and // that might be a local table if name___1 is used. We hereby define that ___1 searches only in // the local table, not the path. Local filters have a Bloom filter of all 1s -// obsolete if(unlikely(AR(g)&ARLOCALTABLE)){bloom=0; v=(A*)&iotavec-IOTAVECBEGIN+0;} // no bloom, empty path -// obsolete NOUNROLL do{A gn=*v--; if((bloom&~LOCBLOOM(g))==0){READLOCK(g->lock) A res=jtprobe(jt,string,hash,g); // Because the global tables are grossly overprovisioned for symbol chains, there is a very good chance that a symbol that misses // in this table will hit an empty chain. This is our Bloom filter. We check that, and if the chain is empty, we call it a miss without locking the table. // That's OK, because this call could have come a few nanoseconds later -// obsolete NOUNROLL do{A gn=*v--; if((bloom&~LOCBLOOM(g))==0 && *(chainbase=&LXAV0(g)[SYMHASH((UI4)hash,AN(g)-SYMLINFOSIZE)])!=0){ // symbol might be in table, and the chain is not empty... scaf remove Bloom, use 1 bit per chain NOUNROLL do{A gn=*v--; I chainno=SYMHASH((UI4)hash,AN(g)-SYMLINFOSIZE); // hashchain number, for fetching the Bloom filter and starting the chain search if(BLOOMTEST(BLOOMBASE(g),chainno)){ // symbol might be in table... READLOCK(g->lock) // we have to take a lock before chasing the hashchain @@ -448,8 +437,6 @@ A jtsyrd1(J jt,C *string,UI4 hash,A g){A*v,x,y; // same, but return the locale in which the name is found, and no ra(). Takes readlock on searched locales. Return 0 if not found A jtsyrd1forlocale(J jt,C *string,UI4 hash,A g){ RZ(g); F1PREFIP; // make sure there is a locale... -// obsolete I bloom=BLOOMMASK(hash); -// obsolete A *v=LOCPATH(g); NOUNROLL do{A gn=*v--; A y; I chainno=SYMHASH((UI4)hash,AN(g)-SYMLINFOSIZE); if((bloom&~LOCBLOOM(g))==0){READLOCK(g->lock) y=probex((I)jtinplace&255,string,SYMORIGIN,hash,g); READUNLOCK(g->lock) if(y){break;}} g=gn;}while(g); // return when name found. A *v=LOCPATH(g); NOUNROLL do{A gn=*v--; A y; I chainno=SYMHASH((UI4)hash,AN(g)-SYMLINFOSIZE); if(BLOOMTEST(BLOOMBASE(g),chainno)){READLOCK(g->lock) y=(probe)((I)jtinplace&255,string,SYMORIGIN,((UI8)(hash)<<32)+(UI4)LXAV0(g)[chainno]); READUNLOCK(g->lock) if(y){break;}} g=gn;}while(g); // return when name found. R g; } @@ -468,7 +455,6 @@ static A jtlocindirect(J jt,I n,C*u,I hash){A x;C*s,*v,*xv;I k,xn; ASSERT(k<256,EVLIMIT); if(likely(!BETWEENC(v[0],'0','9'))){ // is normal name? if(likely(g==0)){ // first time through -// obsolete y=QCWORD(jtprobe((J)((I)jt+k),v,(UI4)hash,jt->locsyms)); // look up local first. y=QCWORD(probex(k,v,SYMORIGIN,hash,jt->locsyms)); // look up local first. if(y==0)y=QCWORD(jtsyrd1((J)((I)jt+k),v,(UI4)hash,jt->global));else{rapos(y,y);} // if not local, start in implied locale. ra to match syrd }else y=QCWORD(jtsyrd1((J)((I)jt+k),v,(UI4)nmhash(k,v),g)); // look up later indirect locatives, yielding an A block for a locative @@ -525,8 +511,6 @@ A jtsyrd(J jt,A a,A locsyms){A g; ARGCHK1(a); if(likely(!(NAV(a)->flag&(NMLOC|NMILOC)))){A val; // If there is a local symbol table, search it first -// obsolete if(val=jtprobe((J)((I)jt+NAV(a)->m),NAV(a)->s,NAV(a)->hash,locsyms)){if(ISRAREQD(val))rapos(QCWORD(val),val); R val;} // return flagging the result if local. Value pointers in symbols have QCSYMVAL semantics -// obsolete if(val=jtprobe((J)((I)jt+NAV(a)->m),NAV(a)->s,NAV(a)->hash,locsyms)){if(unlikely(ISRAREQD(val)))raposlocalqcgsv(QCWORD(val),QCPTYPE(val),val); R val;} // return flagging the result if local. Value pointers in symbols have QCSYMVAL semantics if(val=probex(NAV(a)->m,NAV(a)->s,SYMORIGIN,NAV(a)->hash,locsyms)){if(unlikely(ISRAREQD(val)))raposlocalqcgsv(QCWORD(val),QCPTYPE(val),val); R val;} // return flagging the result if local. Value pointers in symbols have QCSYMVAL semantics g=jt->global; // Continue with the current locale }else{A val; // locative @@ -593,9 +577,7 @@ static I jtsyrdinternal(J jt, A a, I component){A g=0;L *l; g=jt->global; // Continue with the current locale } else RZ(g=sybaseloc(a)); // look up locative; error possible in name, return 0 // we store an extra 0 at the end of the path to allow us to unroll this loop once -// obsolete I bloom=BLOOMMASK(hash); A *v=LOCPATH(g); -// obsolete NOUNROLL do{A gn=*v--; if((bloom&~LOCBLOOM(g))==0){READLOCK(g->lock) l=jtprobeforsym((J)((I)jt+stringlen),string,hash,g); if(l){goto gotval;} READUNLOCK(g->lock)} g=gn;}while(g); // exit loop when found NOUNROLL do{A gn=*v--; I chainno=SYMHASH((UI4)hash,AN(g)-SYMLINFOSIZE); if(BLOOMTEST(BLOOMBASE(g),chainno)){READLOCK(g->lock) l=jtprobeforsym((J)((I)jt+stringlen),string,hash,g); if(l){goto gotval;} READUNLOCK(g->lock)} g=gn;}while(g); // exit loop when found R 0; // not found, locks released gotval: ; @@ -761,12 +743,10 @@ I jtsymbis(J jt,A a,A w,A g){F2PREFIP; valtype|=QCNAMED|(LOCALRA?QCRAREQD:REPSGN(wt)&QCRAREQD); // enter QCSYMVAL semantics; ra needed if sparse }else{ // global table SYMRESERVE(1) // before we go into lock, make sure we have a symbol to assign to -// obsolete I bloom=BLOOMMASK(NAV(a)->hash); // calculate Bloom mask outside of lock C *bloombase=BLOOMBASE(g); I chainno=SYMHASH(NAV(a)->hash,AN(g)-SYMLINFOSIZE); // get addr of Bloom filter and the location we are storing to valtype|=QCNAMED|QCRAREQD; // must flag local/global type in symbol e=probeis(a, g); // get the symbol address to use, old or new. This returns holding a lock on the locale // if we are writing to a non-local table, update the table's Bloom filter. -// obsolete BLOOMOR(g,bloom); // requires writelock on g BLOOMSET(bloombase,chainno); // g is under lock. This modifies the shared memory every time - might be better to write only when chain is empty // A couple of debugging flags are set during assignment. We don't bother for local names if(unlikely(JT(jt,stch)!=0))e->flag|=LCH; // update 'changed' flag if enabled - needed only for globals @@ -813,13 +793,11 @@ I jtsymbis(J jt,A a,A w,A g){F2PREFIP; }else{ // x exists, is either read-only or memory-mapped, and is not rewriting the previous value ASSERTGOTO(!(AFRO&xaf),EVRO,exitlock); // error if read-only value -// obsolete if(x!=w){ // replacing name with different mapped data. If data is the same, just leave it alone // no need to store valtype - that can't change from noun (because must be DIRECT below) I wt=AT(w); I wn=AN(w); I wr=AR(w); I m=wn<0,EVDOMAIN,exitlock); // boxed, extended, etc can't be assigned to memory-mapped array ASSERTGOTO(AM(x)>=m,EVALLOC,exitlock); // ensure the file area can hold the data. AM of NJA is allosize AT(x)=wt; AN(x)=wn; AR(x)=(RANKT)wr; MCISH(AS(x),AS(w),wr); MC(AV(x),AV(w),m); // copy in the data. Can't release the lock while we are copying data in. -// obsolete } x=0; // repurpose x to be the value needing fa - indicate no further fa needed } }else x=0; // repurpose x to be the value needing fa diff --git a/jsrc/sc.c b/jsrc/sc.c index 292bf5d65..573c4ffe9 100644 --- a/jsrc/sc.c +++ b/jsrc/sc.c @@ -68,7 +68,6 @@ DF2(jtunquote){A z; A cachedlocale=FAV(self)->localuse.lu0.cachedloc; UI4 vtime=FAV(self)->lu2.refvalidtime; // fetch before we read reftime as atomic if(vtime==ACVCACHEREAD){ // is previous lookup still valid // Short caching: the previous lookup can be reused because there have been no assignments -// obsolete raposgblqcgsv(QCWORD(fs),QCPTYPE(fs),fs); // ra to match syrd1 scaf QCWORD not needed raposgblqcgsv(fs,0,fs); // ra to match syrd1. The 0 guarantees no recursion if(unlikely(NAV(thisname)->flag&NMLOC)){ // is this a (necessarily direct) locative? // see if the locale is cached. public_z_ =: entry_loc_ where entry_loc will have the locale pointer @@ -93,7 +92,6 @@ DF2(jtunquote){A z; if(likely(!(nmflgs&(NMLOC|NMILOC|NMIMPLOC)))) { // simple name, and not u./v. // We must not use bucket info for the local lookup, because the reference may have been created in a different context J jtx=(J)((I)jt+NAV(thisname)->m); C *sx=NAV(thisname)->s; UI4 hashx=NAV(thisname)->hash; -// obsolete if(unlikely(AR(jt->locsyms)&ARHASACV)){if(unlikely((fs=CLRNAMEDLOC(jtprobe(jtx,sx,hashx,jt->locsyms)))!=0)){raposlocal(QCWORD(fs),fs); goto deflocal;}} // ACV is probably not in local, and we can even check to see. Set not-NAMEDLOC. ra to match syrd1 if(unlikely(AR(jt->locsyms)&ARHASACV)){if(unlikely((fs=CLRNAMEDLOC(probex(NAV(thisname)->m,sx,SYMORIGIN,hashx,jt->locsyms)))!=0)){raposlocal(QCWORD(fs),fs); goto deflocal;}} // ACV is probably not in local, and we can even check to see. Set not-NAMEDLOC. ra to match syrd1 fs=jtsyrd1(jtx,sx,hashx,jt->global); // not found in local, search global // leave LOCINCRDECR unset and jt->global unchnged @@ -108,7 +106,6 @@ DF2(jtunquote){A z; } fs=jtsyrd1((J)((I)jt+NAV(thisname)->m),NAV(thisname)->s,NAV(thisname)->hash,explocale); // Look up the name starting in the locale of the locative }else{ // u./v. We have to look at the assigned name/value to know whether this is an implied locative (it usually is) -// obsolete if(likely((fs=CLRNAMEDLOC(jtprobe((J)((I)jt+NAV(thisname)->m),NAV(thisname)->s,NAV(thisname)->hash,jt->locsyms)))!=0)){ // look only in local symbols. Set not-NAMEDLOC if(likely((fs=CLRNAMEDLOC(probex(NAV(thisname)->m,NAV(thisname)->s,SYMORIGIN,NAV(thisname)->hash,jt->locsyms)))!=0)){ // look only in local symbols. Set not-NAMEDLOC // u/v, assigned by xdefn. Implied locative. Switch locals and globals to caller's environment jt->locsyms=(A)AM(jt->locsyms); explocale=AKGST(jt->locsyms); // move to new locals and their globals (up the local-sym chain) @@ -338,7 +335,6 @@ A jtnamerefacv(J jt, A a, A val){A y;V*v; // In any case we install the current asgnct and the looked-up value (unflagged). We will know that the cached value is not a pun in type I flag2=(!!(NAV(a)->flag&NMCACHED) | (jt->namecaching & !(NAV(a)->flag&(NMILOC|NMDOT|NMIMPLOC))))<flag&VASGSAFE)+(VJTFLGOK1|VJTFLGOK2), v->mr,lrv(v),rrv(v)); // create value of 'name~', with correct rank, part of speech, and safe/inplace bits -// obsolete if(likely(val!=0)){if(LOCALRA||ISGLOBAL(val))fa(QCWORD(val))}else val=(A)QCVERB; // release the value, now that we don't need it (if global). If val was 0, get flags to install into reference to indicate [: is a verb if(likely(val!=0)){if(ISFAOWED(val))fa(QCWORD(val))}else val=(A)QCVERB; // release the value, now that we don't need it (if global). If val was 0, get flags to install into reference to indicate [: is a verb RZ(z); // abort if reference not allocated if(likely(!(NAV(a)->flag&(NMILOC|NMIMPLOC)))){FAV(z)->localuse.lu1.cachedlkp=QCWORD(val); FAV(z)->lu2.refvalidtime=ACVCACHEREAD;} // install cachelet of lookup, but never if indirect locative. No QC diff --git a/jsrc/sl.c b/jsrc/sl.c index e40a76fe1..f6d177213 100644 --- a/jsrc/sl.c +++ b/jsrc/sl.c @@ -215,7 +215,6 @@ A jtstcreate(J jt,I1 k,I p,I n,C*u){A g,x,xx;L*v; LX *hv=LXAV0(JT(jt,stloc))+SYMHASH(hsh,AN(JT(jt,stloc))-SYMLINFOSIZE); // get hashchain base in stloc LX tx=SYMNEXT(*hv); if(tx!=0)NOUNROLL while(SYMNEXT(sympv[tx].next)!=0)tx=SYMNEXT(sympv[tx].next); // tx->last in chain, or 0 if chain empty v=symnew(hv,tx); v->name=x; v->fval=g; ACINITZAP(g); // install the new locale at end of chain; put name into block; put locale pointer into fval; ZAP to match store of value -// obsolete LOCBLOOM(g)=0; // Init Bloom filter to 'nothing assigned' ACINITZAP(x); ACINIT(x,ACUC2) // now that we know we will succeed, transfer ownership to name to the locale and stloc, one each AR(g)=ARNAMED; // set rank to indicate named locale LXAV0(g)[SYMLEXECCT]=((k+1)<=0); // put the locale into the numbered list; exit if error (with lock removed); zap g I nmlen=sprintf(NAV(x)->s,FMTI,n); AN(x)=nmlen; NAV(x)->m=nmlen; // install true locale number and length of name LOCNUMW(g)=(A)n; // save locale# in SYMLINFO -// obsolete LOCBLOOM(g)=0; // Init Bloom filter to 'nothing assigned'. Must be after installnl LOCPATH(g)=JT(jt,zpath); // zpath is permanent, no ras needed Must be after installnl WRITEUNLOCK(JT(jt,stlock)) LOCNAME(g)=x; // set name pointer in SYMLINFO @@ -301,7 +299,6 @@ F1(jtlocsizes){I p,q,*v; } /* 9!:39 default locale size set */ // jtprobe, with readlock taken on stlock -// obsolete static A jtprobestlock(J jt, C *u,UI4 h){F1PREFIP; READLOCK(JT(jt,stloc)->lock) A z=jtprobe(jtinplace,u,h,JT(jt,stloc)); READUNLOCK(JT(jt,stloc)->lock) R z;} static A jtprobestlock(J jt, C *u,UI4 h){F1PREFIP; READLOCK(JT(jt,stloc)->lock) A z=probex((I)jtinplace&255,u,SYMORIGIN,h,JT(jt,stloc)); READUNLOCK(JT(jt,stloc)->lock) R z;} // find the symbol table for locale with name u which has length n and hash/number bucketx @@ -535,7 +532,6 @@ static F2(jtloccre){A g,y,z=0;C*s;I n,p;A v; SYMRESERVE(2) // make sure we have symbols to insert, for the locale itself A op=0; // old path, if there is one WRITELOCK(JT(jt,locdellock)) WRITELOCK(JT(jt,stloc)->lock) // take a write lock until we have installed the new locale if any. No errors! We need both locks, in this order (delete calls symfree, which takes locks in this order) -// obsolete if(v=jtprobe((J)((I)jt+n),s,(UI4)nmhash(n,s),JT(jt,stloc))){ if(v=probex(n,s,SYMORIGIN,nmhash(n,s),JT(jt,stloc))){ // named locale exists. It may be zombie or not, but we have to keep using the same locale block, since it may be out there in paths g=v; @@ -631,7 +627,6 @@ static F1(jtlocmaplocked){A g,q,x,y,*yv,z,*zv;I c=-1,d,j=0,m,*qv,*xv; F1(jtlocmap){READLOCK(JT(jt,stlock)) READLOCK(JT(jt,stloc)->lock) READLOCK(JT(jt,symlock)) A z=jtlocmaplocked(jt,w); READUNLOCK(JT(jt,stlock)) READUNLOCK(JT(jt,stloc)->lock) READUNLOCK(JT(jt,symlock)) R z;} // recalculate Bloom filter in table w -// obsolete SYMWALK(jtaccumbloom,B,B01,0,0,(LOCBLOOM(w)|=BLOOMMASK(NAV(d->name)->hash))&&0,;) SYMWALK(jtaccumbloom,B,B01,0,0,BLOOMSET(BLOOMBASE(w),i)&&0,;) // i is chain#. For each defined symbol, set the bit // 18!:_5 return bloom filter, as character string @@ -646,7 +641,6 @@ F1(jtresetbloom){A g; ASSERT(!AR(w),EVRANK); // now always boxed: must be atom RZ(g=locale(0,w)); // point to locale, if no error ASSERT(AR(g)&ARNAMED,EVDOMAIN) // locale must be named -// obsolete I oldbloom=LOCBLOOM(g); LOCBLOOM(g)=0; // get old value of Bloom filter, init new A oldbloom=str(BLOOMLEN(g),BLOOMBASE(g)); BLOOMCLEAR(g); jtaccumbloom(jt,0,g); // roll up all Bloom filters RETF(oldbloom); // return old Bloom (character string) @@ -725,7 +719,6 @@ B jtlocdestroy(J jt,A g){ while(*path)--path; fa(UNvoidAV1(path)) // delete the path too. block is recursive; must fa() to free sublevels // Set path pointer to 0 (above) to indicate it has been emptied; clear Bloom filter. Leave hashchains since the Bloom filter will ensure they are never used BLOOMCLEAR(g); // clear Bloom filter -// obsolete LOCBLOOM(g)=0; // lower the usecount. The locale and the name will be freed when the usecount goes to 0 fa(g); // The current implied locale can be deleted only after it leaves execution, i. e. after it returns to immex in all threads where it is current. diff --git a/jsrc/sn.c b/jsrc/sn.c index 1913ba788..63a837753 100644 --- a/jsrc/sn.c +++ b/jsrc/sn.c @@ -241,7 +241,6 @@ F1(jtex){A*wv,y,z;B*zv;I i,n; A locfound; // get the locale in which the name is defined - must exist. if(y&&(locfound=syrdforlocale(y))){ // if debug turned on, see if the value is on the debug stack. The name must still be in the locale we found it in, if it is on our debug stack. -// obsolete if(jt->uflags.trace&TRACEDB){READLOCK(locfound->lock) A v=jtprobe((J)((I)jt+NAV(y)->m),NAV(y)->s,NAV(y)->hash,locfound); A rres=(A)1; if(v)rres=redef(mark,v); READUNLOCK(locfound->lock) RZ(rres)} if(jt->uflags.trace&TRACEDB){READLOCK(locfound->lock) A v=probex(NAV(y)->m,NAV(y)->s,SYMORIGIN,NAV(y)->hash,locfound); A rres=(A)1; if(v)rres=redef(mark,v); READUNLOCK(locfound->lock) RZ(rres)} WRITELOCK(locfound->lock) if(unlikely(jtprobedel((J)((I)jt+NAV(y)->m),NAV(y)->s,NAV(y)->hash,locfound)))ACVCACHECLEAR; // delete the symbol (incl name and value) in the locale in which it is defined diff --git a/jsrc/va.h b/jsrc/va.h index 7d3804df4..c65a05976 100644 --- a/jsrc/va.h +++ b/jsrc/va.h @@ -42,7 +42,6 @@ #define VIPOKW ((I)1<3?n:m; // if inner-loop len > 1, there are 2 loops, use mf; if inner-loop len=1, use the 1-loop value -// obsolete mf=1; // suppress the outer loop, leaving only the loop over m and n }else{ // Sparse setup: move the block-local variables to longer-lived ones. We are trying to reduce register pressure // repurpose ak/wk/mf/nf to hold acr/wcr/af/wf, which we will pass into vasp. This allows acr/wcr/af/wf to be block-local @@ -631,7 +630,6 @@ static A jtva2(J jt,AD * RESTRICT a,AD * RESTRICT w,AD * RESTRICT self,UI allran // migration is possible flagorign|=((I)jtinplace>>VIPWFLONGX)&(nf!=1); // repetition also comes if nf is not 1 and WFLONG. In this case n must be 1 & thus nop flag set yet m*=migrmf; n*=nf; // propagate mf and nf down -// obsolete mf=1; // no outer loops. nf immaterial. aawwzk does not need to change since it will not be used }else{aawwzknfxrz[6]=--nf; aawwzknfxrz[9]=(mf-1)*aawwzknfxrz[4];} // All 4 loops (normal case since rank given). nf is outer loop repeat count-1. zend ([9]) is offset to result of last iteration // Use new semantics for m and n aawwzknfxrz[5]=m; // parm n is orig m, i. e. the length of the inner or only loop. @@ -678,16 +676,11 @@ static A jtva2(J jt,AD * RESTRICT a,AD * RESTRICT w,AD * RESTRICT self,UI allran // Also, if the operation is one that may abort, we suppress inplacing it if the user can't handle early assignment. // Finally, if a==w suppress inplacing, in case the operation must be retried (we could check which ones but they are // just not likely to be used reflexively) -// obsolete // If the operation is one that can fail partway through, don't allow it to overwrite a zombie input unless so enabled by the user -// obsolete // The ordering here assumes that jtinplace will usually be set -// obsolete if(ASGNINPLACESGN(SGNIF(jtinplace,JTINPLACEWX),w)){z=w; I wt=AT(w), zt=rtype((I)jtinplace); zt=zt?zt:wt; if(unlikely(TYPESNE(wt,zt)))MODBLOCKTYPE(z,zt) // Uses JTINPLACEW==1 -// obsolete }else if(ASGNINPLACESGN(SGNIF(jtinplace,JTINPLACEAX),a)){z=a; I at=AT(a), zt=rtype((I)jtinplace); zt=zt?zt:at; if(unlikely(TYPESNE(at,zt)))MODBLOCKTYPE(z,zt) // Uses JTINPLACEA==2 I ipw=ASGNINPLACENEG(SGNIF(jtinplace,JTINPLACEWX),w), ipa=ASGNINPLACENEG(SGNIF(jtinplace,JTINPLACEAX),a), zt=rtype((I)jtinplace); // get type of result; is w inplaceable? if((ipw|ipa)<0){ // see if either w or a is inplaceable // we are reusing an argument (ipw is neg if it's w, which has priority); make sure the type is updated to the result type z=ipw<0?w:a; // z=inplaceable arg; if(unlikely((zt&~AT(z))!=0)){ // if type changes (zt!=incumbent and zt!=0)... zt does not have upper flag bits -// obsolete MODBLOCKTYPE(z,zt) // the type of inplaceable z must change. But if z is UNINCORPABLE, it might be virtual. Realizing it is a losing move. And, we don't change the type of an UNINCORPABLE so that the caller // that created it doesn't have to keep reinitializing the type. So, we give up on inplacing it. If both args are inplaceable, we try a (which might have the right type). If neither works, we allocate if(AFLAG(z)&AFUNINCORPABLE){ @@ -727,32 +720,27 @@ allocate:; // come here if no inplaceable block could have the type changed // m is the length of the inner loop, with flags: complement=single loop of length ~m, otherwise each loop has length m>>1, and LSB of m is set if a atom is repeated // aawwzknfxrz[5] is the number of outer inner loops, used only if m>0. n*m cannot=0. // Each release, monitor that clang brings adocvfn into register early to advance the expected misprediction. -// obsolete I i=mf; I jj=aawwzknfxrz[6]; // number of outer-outer loops, number-1 of each outer-inner loop lp000: ; {I lrc=((AHDR2FN*)adocvfn)AH2A(aawwzknfxrz[5],m,av,wv,zv,jt); // run one section. Result is EOK normally, otherwise error code, as examined below if(unlikely(lrc!=EVOK)){ // scaf can make EVOK=0 // section did not complete normally. -// obsolete if(unlikely(lrc<0)){I absn=(m>>1); absn=m<0?1:absn; mulofloloc=(mf-i)*aawwzknfxrz[5]*absn+~lrc; aawwzknfxrz[8]=EWOVIP+EWOVIPMULII; goto lp000e;} // integer multiply overflow. ~lrc is index of failing location; create global failure index. Abort the computation to retry if(unlikely(lrc<0)){mulofloloc=((zv-CAV(z))>>LGSZI)+~lrc; aawwzknfxrz[8]=EWOVIP+EWOVIPMULII; goto lp000e;} // integer multiply overflow. ~lrc is index of failing location; create global failure index. Abort the computation to retry if(lrc=0){A zz;C *zzv;I zzk; // Here for overflow that can be corrected in place. The routines use the old semantics for m and n, so we convert them back n=(m>>1)^-(m&1); n=m<0?1:n; // original n is 1 if m is complementary; otherwise m>>1, complemented if x is repeated @@ -769,11 +757,9 @@ allocate:; // come here if no inplaceable block could have the type changed DQ(mulofloloc, *zzvd++=(D)*zvi++;); // convert the multiply results to float. mulofloloc is known negative, and must be complemented // Now repeat the processing. Unlike with add/subtract overflow, we have to match up all the argument atoms {C *av=CAV(a); C *wv=CAV(w); -// obsolete I i=mf; i=jj<0?1:i; I jj=aawwzknfxrz[6]; I mend=aawwzknfxrz[9]*(SZD/SZI)+(I)zzv; // extract offset to end buffer, convert it to D length, relocate to new output area while(1){ tymesIIO(n,m,(I*)av,(I*)wv,(D*)zzv,mulofloloc); -// obsolete if(!--i)break; if((I)zzv==mend)break; mulofloloc-=m*(n^REPSGN(n)); aawwzknfxrz[7]=--jj; jj=REPSGN(jj); zzv+=zzk; av+=aawwzknfxrz[1+jj]; wv+=aawwzknfxrz[3+jj]; jj=aawwzknfxrz[7+jj]; // jj1 is -1 on the last inner iter, where we use outer incr } } @@ -791,10 +777,8 @@ allocate:; // come here if no inplaceable block could have the type changed // we must multiply out the repeat to leave n=1. av=CAV(nipw?w:a); // point to the not-in-place argument I nsgn=SGNTO0(n); n^=REPSGN(n); if(nipw==nsgn){m*=n; n=1;} n^=-nipw; // force n to <=1; make n flag indicate whether args were switched -// obsolete I i=mf; i=jj<0?1:i; I jj=aawwzknfxrz[6]; I mend=aawwzknfxrz[9]+(I)zv; NOUNROLL while(1){(repairfn)AH2A(n,m,av,zv,zzv,jt); if((I)zv==mend)break; aawwzknfxrz[7]=--jj; jj=REPSGN(jj); zv+=aawwzknfxrz[4]; zzv+=zzk; av+=aawwzknfxrz[2*nipw+1+jj]; jj=aawwzknfxrz[7+jj];} // jj1 is -1 on the last inner iter, where we use outer incr -// obsolete if(!--i)break; aawwzknfxrz[7]=--jj; jj=REPSGN(jj); zv+=aawwzknfxrz[4]; zzv+=zzk; av+=aawwzknfxrz[2*nipw+1+jj]; jj=aawwzknfxrz[7+jj];} // jj1 is -1 on the last inner iter, where we use outer incr } } R zz; // Return the result after overflow has been corrected diff --git a/jsrc/vb.c b/jsrc/vb.c index 396f290f5..6a1a79237 100644 --- a/jsrc/vb.c +++ b/jsrc/vb.c @@ -370,7 +370,6 @@ DF2(jtifbebar){A y,z;C*av,*wv;I c,d,i,k=0,m,n,p,*yv,*zu,*zv; switch(d){ case -1: R mtv; case -4: R jtupon2cell(jt,a,w,self); // revert if recoverable error -// obsolete R icap(ebarvec(a,w)); } } if((-m&-n)>=0){R icap(ebar(a,w));} // empty argument. diff --git a/jsrc/ve.c b/jsrc/ve.c index 0ba466393..e2eeecc1f 100644 --- a/jsrc/ve.c +++ b/jsrc/ve.c @@ -421,8 +421,7 @@ primop256CE(tymesEE,0,E,__m256d sgnbit=_mm256_broadcast_sd((D*)&Iimin); __m256d APFX( tymesEE, E,E,E, TYMESE,NAN0;,ASSERTWR(!NANTEST,EVNAN); R EVOK;) #endif -#if 0 // obsolete this template used to debug primop256CE -#define fz 0 +#if 0 #define fz 0 #define CET E #define cepref __m256d sgnbit=_mm256_broadcast_sd((D*)&Iimin); __m256d mantmask=_mm256_broadcast_sd((D*)&(I){0x000fffffffffffff}); NAN0; #define ceprefL PREFNULL // replaced in main line @@ -535,8 +534,7 @@ rdlp: ; /* come here to fetch next batch & store it without masking */ } #endif -#if 0 // obsolete This template used to debug APFX - I divEE(I n,I m,E* RESTRICTI x,E* RESTRICTI y,E* RESTRICTI z,J jt){E u;E v; +#if 0 I divEE(I n,I m,E* RESTRICTI x,E* RESTRICTI y,E* RESTRICTI z,J jt){E u;E v; NAN0; // this supports only scalar op scalar u = *x; v=*y; diff --git a/jsrc/vfrom.c b/jsrc/vfrom.c index 7cfe56924..4c33bf6a1 100644 --- a/jsrc/vfrom.c +++ b/jsrc/vfrom.c @@ -658,7 +658,6 @@ DF2(jtsfrom){ mustbox:; } // If we couldn't handle it as a special case, do it the hard way -// obsolete A z; RETF(from(IRS1(a,0L,1L,jtbox,z),w)); // reverting by hand RETF(fork242(jt,a,w,self)) // revert using the fork for (f@[ g ]) } /* (<"1 a){w */ diff --git a/jsrc/vg.c b/jsrc/vg.c index 21b92bd28..7baa86d3e 100644 --- a/jsrc/vg.c +++ b/jsrc/vg.c @@ -782,7 +782,6 @@ DF2(jtordstat){A q,t=0;I j,m,m0,m1,n,wt;D *qv; I i=NRANDS-1; // i points to the next random number to draw ARGCHK2(a,w); n=AN(w); wt=AT(w); RE(j=i0(a)); -// obsolete if(((4-n)&((AR(a)|(1^AR(w)))-1)&(-(wt&FL+INT)))>=0)R from(a,grade2(w,w)); // if not int/float, or short, or not (atom a and list w), do full grade if(((4-n)&((AR(a)|(1^AR(w)))-1)&(-(wt&FL+INT)))>=0)R jthook2cell(jt,a,w,self); // if not int/float, or short, or not (atom a and list w), do full grade if((UI)j>=(UI)n){j+=n; ASSERT((UI)j<(UI)n,EVINDEX);} // deal a bunch of random floats to provide pivots. We reuse them if needed diff --git a/jsrc/viavx.c b/jsrc/viavx.c index ebb5d96ee..0735ac0c8 100644 --- a/jsrc/viavx.c +++ b/jsrc/viavx.c @@ -1281,7 +1281,6 @@ F2(jteps){I l,r; // I.@~: y does not have IRS DF1(jtnubind){ ARGCHK1(w); -// obsolete R ISSPARSE(AT(w))?icap(nubsieve(w)):indexofsub(INUBI,w,w); R unlikely(ISSPARSE(AT(w)))?on1cell(jt,w,self):indexofsub(INUBI,w,w); // revert for sparse } /* I.@~: w */ diff --git a/jsrc/vrand.c b/jsrc/vrand.c index 9415ff218..3feb9ef01 100644 --- a/jsrc/vrand.c +++ b/jsrc/vrand.c @@ -641,7 +641,6 @@ F2(jtrollksub){A z;I an,*av,k,m1,n,p,q,r,sh;UI m,mk,s,t,*u,x=jt->rngdata->rngpar DF2(jtrollk){A g,z;V*sv; ARGCHK3(a,w,self); sv=FAV(self); g=sv->fgh[2]?sv->fgh[2]:sv->fgh[1]; // 2d verb, # or $ -// obsolete if(AT(w)&XNUM+RAT||!(!AR(w)&&1>=AR(a)&&(g==ds(CDOLLAR)||1==AN(a))))R roll(dfv2(z,a,w,g)); // revert if XNUM/RAT or nonatomic w or AR(a)>1 or (?@# with a not a singleton) if(AT(w)&XNUM+RAT||!(!AR(w)&&1>=AR(a)&&((g==ds(CDOLLAR))|(1==AN(a)))))R jtupon2cell(jt,a,w,self); // revert if XNUM/RAT or nonatomic w or AR(a)>1 or (?@# with a not a singleton) RETF(rollksub(a,vi(w))); } /* ?@$ or ?@# or [:?$ or [:?# */ diff --git a/jsrc/vx.c b/jsrc/vx.c index f66175439..0e3e5dfff 100644 --- a/jsrc/vx.c +++ b/jsrc/vx.c @@ -254,7 +254,6 @@ DF1(jtdigits10){ // "."0@": } } // if none of the fast cases applies, revert -// obsolete EPILOG(rank1ex0(thorn1(w),DUMMYSELF,jtexec1)); RETF(on1cell(jt,w,self)); } diff --git a/jsrc/vz.c b/jsrc/vz.c index 3e36837da..52ef9bcac 100644 --- a/jsrc/vz.c +++ b/jsrc/vz.c @@ -280,7 +280,6 @@ DF1(jtexppi){A z;B b;D r,th,y;I k;Z*v,t; F1RANK(0,jtexppi,self); if(!(CMPX&AT(w)))goto revert; // if not complex, revert v=ZAV(w); r=exp(PI*v->re); y=v->im; if(b=0>y)y=-y; // take exp of real part, set y=|imaginary part| -// obsolete th=y-2*(I)(y/2); k=(I)(2*th); if(k!=2*th)k=-1; else if(b&&k)k=4-k; // th=|im| (mod 2); k = twice that th=y-2*(I)(y/2); k=(I)(2*th); if(k!=2*th)goto revert; else if(b&&k)k=4-k; // th=|im| (mod 2); k = twice that; if th is not exact multiple of 0.5, revert if(!((UI)k<=(UI)3))goto revert; // if k is not an exact multiple of 0.5, revert GAT0(z,CMPX,1,0); ZAV0(z)[0].re=ZAV0(z)[0].im=0; DAV0(z)[k&1]=r*(1-(k&2)); // set result to 0, then store into real or imag, possibly changing sign, with exact 0 for one component (which is the point) diff --git a/jsrc/x.c b/jsrc/x.c index 06a0ff068..07c6db48c 100644 --- a/jsrc/x.c +++ b/jsrc/x.c @@ -345,8 +345,7 @@ void jtforeigninit(J jt){UI i; MN(128,8) XPRIM(VERB, jtqhash12, jtqhash12, VASGSAFE|VJTFLGOK1|VJTFLGOK2,VF2NONE,RMAX,RMAX,RMAX); MN(128,10) XPRIM(VERB, jtludecomp, jtludecomp, VASGSAFE,VF2NONE,RMAX, RMAX,RMAX); MN(18,6) XPRIM(VERB, jtresetbloom, 0, VFLAGNONE,VF2NONE,RMAX,RMAX,RMAX); -#if 0 // obsolete but not dead - MN(18,7) XPRIM(VERB, jtsetpermanent, 0, VFLAGNONE,VF2NONE,RMAX,RMAX,RMAX); +#if 0 MN(18,7) XPRIM(VERB, jtsetpermanent, 0, VFLAGNONE,VF2NONE,RMAX,RMAX,RMAX); #endif MN(0,-1) XPRIM(VERB, jtskipinscript, 0, VFLAGNONE,VF2NONE,RMAX,RMAX,RMAX); @@ -381,9 +380,7 @@ void jtforeigninit(J jt){UI i; // called at initialization after memory reset, to assign cocurrent_z_ and coclass_z_. The 18!:4 block is at the end of foreignA and is a read-only value I jtforeignassigninit(J jt){A nm;L *e; RZ(nm=nfs(12,"cocurrent_z_")); symbis(nm,(A)&foreignA[(sizeof(foreignA)/sizeof(foreignA[0]))-1],0); e=probeisres(nm, *JT(jt,zpath)); e->flag|=LREADONLY; -// obsolete WRITEUNLOCK((*JT(jt,zpath))->lock) // probe takes a lock RZ(nm=nfs(10,"coclass_z_")); symbis(nm,(A)&foreignA[(sizeof(foreignA)/sizeof(foreignA[0]))-1],0); e=probeisres(nm, *JT(jt,zpath)); e->flag|=LREADONLY; -// obsolete WRITEUNLOCK((*JT(jt,zpath))->lock) R 1; }