Skip to content

Commit abffee0

Browse files
committed
Expunge LOCALRA; tweaks to symbis; version to beta-27
1 parent a4869e7 commit abffee0

File tree

12 files changed

+39
-32
lines changed

12 files changed

+39
-32
lines changed

jsrc/cx.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,8 @@ DF2(jtxdefn){
300300
L *sympv=SYMORIGIN; // bring into local
301301
L *ybuckptr = &sympv[LXAV0(locsym)[(US)yxbucks]]; // pointer to sym block for y, known to exist
302302
if(likely(w!=0)){ // If y given, install it & incr usecount as in assignment. Include the script index of the modification
303-
I vtype=QCNAMED|(LOCALRA?QCRAREQD:REPSGN(AT(w))&QCRAREQD)|ATYPETOVALTYPE(AT(w)); // install QCSYMVAL flags
303+
// obsolete I vtype=QCNAMED|(REPSGN(AT(w))&QCRAREQD)|ATYPETOVALTYPE(AT(w)); // install QCSYMVAL flags: named, with type
304+
I vtype=unlikely(ISSPARSE(AT(w)))?QCNAMED+QCRAREQD+VALTYPESPARSE:QCNAMED+QCNOUN; // install QCSYMVAL flags: named, with type; FA needed iff sparse. Must be a noun
304305
ybuckptr->fval=MAKEFVAL(w,vtype); ybuckptr->sn=jt->currslistx; // finish the assignment, with QCSYMVAL semantics
305306
// If input is abandoned inplace and not the same as x, DO NOT increment usecount, but mark as abandoned and make not-inplace. Otherwise ra
306307
// We can handle an abandoned argument only if it is direct or recursive, since only those values can be assigned to a name
@@ -319,7 +320,8 @@ DF2(jtxdefn){
319320
if(a!=0){
320321
L *xbuckptr = &sympv[LXAV0(locsym)[yxbucks>>16]]; // pointer to sym block for x
321322
if(!C_CRC32C&&xbuckptr==ybuckptr)xbuckptr=xbuckptr->next+sympv;
322-
I vtype=QCNAMED|(LOCALRA?QCRAREQD:REPSGN(AT(a))&QCRAREQD)|ATYPETOVALTYPE(AT(a)); // install QCSYMVAL flags
323+
// obsolete I vtype=QCNAMED|(LOCALRA?QCRAREQD:REPSGN(AT(a))&QCRAREQD)|ATYPETOVALTYPE(AT(a)); // install QCSYMVAL flags
324+
I vtype=unlikely(ISSPARSE(AT(a)))?QCNAMED+QCRAREQD+VALTYPESPARSE:QCNAMED+QCNOUN; // install QCSYMVAL flags: named, with type; FA needed iff sparse
323325
xbuckptr->fval=MAKEFVAL(a,vtype); xbuckptr->sn=jt->currslistx;
324326
if(likely(a!=w)&(SGNTO0(AC(a)&(((AT(a)^AFLAG(a))&RECURSIBLE)-1))&((I)jtinplace>>JTINPLACEAX))){
325327
AFLAGORLOCAL(a,AFKNOWNNAMED); xbuckptr->flag=LPERMANENT|LWASABANDONED; ACIPNOABAND(a); ramkrecursv(a);
@@ -427,7 +429,7 @@ nextlinedebug:;
427429
dobblock:
428430
// B-block (present on every sentence in the B-block)
429431
// run the sentence
430-
parseline(z,if((UI)jt->tnextpushp-(UI)old>TPOPSLACK*SZI)tpop(old);,t=0;); // *** run user's line *** sets tcesx to thisline/nextline; t=0 so t doesn't have to be preserved over subrt calls
432+
parseline(z,if((UI)jt->tnextpushp-(UI)old>TPOPSLACKB*SZI)tpop(old);,t=0;); // *** run user's line *** sets tcesx to thisline/nextline; t=0 so t doesn't have to be preserved over subrt calls
431433
// if there is no error, step to next line. debug mode has set the value to use if any, or 0 to request a new line
432434
if(likely(z!=0)){bic=ic; ic-=(tcesx>>(32+TCESXTYPEX+5))+1; // advance to next sentence to be executed, which is NSI, or NSI+1 if BBLOCKEND
433435
// the sequence BBLOCKEND BBLOCKEND indicates that the second BBLOCKEND was originally an END that went to NSI which was BBLOCK, i. e. end. for an if./select. followed by BBLOCK.
@@ -466,13 +468,13 @@ nextlinedebug:;
466468
// Check for assert. Since this is only for T-blocks we tolerate the test (rather than duplicating code)
467469
if(unlikely(TEQ5(tcesx,CASSERT))){
468470
if(JT(jt,assert)){
469-
parseline(t,{if((UI)jt->tnextpushp-(UI)old>TPOPSLACK*SZI)if(likely((tcesx&((UI8)TCESXCECANT<<32))!=0))tpop(old);else z=gc(z,old);},);
471+
parseline(t,{if((UI)jt->tnextpushp-(UI)old>(0)*SZI)if(likely((tcesx&((UI8)TCESXCECANT<<32))!=0))tpop(old);else z=gc(z,old);},); // 0 to force flushes during testcases
470472
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.
471473
if(likely(t!=0)){ // assert without error
472474
t=mtv; // An assert is an entire T-block and must clear t afterward lest t be freed before it is checked by an empty while. So we use a safe permanent value, mtv.
473475
}
474476
}else{--ic; goto nextline;} // if ignored assert, go to NSI
475-
}else{parseline(t,{if((UI)jt->tnextpushp-(UI)old>TPOPSLACK*SZI)if(likely((tcesx&((UI8)TCESXCECANT<<32))!=0))tpop(old);else z=gc(z,old);},);} // no assert: run the line resets tcesx to thisline/nextline
477+
}else{parseline(t,{if((UI)jt->tnextpushp-(UI)old>(TPOPSLACKT)*SZI)if(likely((tcesx&((UI8)TCESXCECANT<<32))!=0))tpop(old);else z=gc(z,old);},);} // no assert: run the line resets tcesx to thisline/nextline
476478
// this is return point from running the line
477479
if(likely(t!=0)){tic=ic,--ic; // if no error, continue on. --ic must be in bounds for a non-assert T block (there must be another control word)
478480
if(unlikely(TXOR5(tcesx,CDO)|jt->uflags.trace))goto nextlinetcesx; // next line not do.; T block extended to more than 1 line (rare).

jsrc/j.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -800,14 +800,13 @@ struct jtimespec jmtfclk(void); //'fast clock'; maybe less inaccurate; intended
800800
#define NTSTACK (1LL<<(AUDITEXECRESULTS?24:14)) // number of BYTES in an allocated block of tstack - pointers to allocated blocks - allocation is bigger to leave this many bytes on boundary
801801
#define NTSTACKBLOCK 2048 // boundary for beginning of stack block
802802

803-
#define TPOPSLACK 1 // number of stacked blocks to allow before we tpop them (in jtxdefn) - 0 means tpop every time
803+
#define TPOPSLACKB 1 // number of stacked blocks to allow before we tpop them (in jtxdefn) - 0 means tpop every time - for B blocks
804+
#define TPOPSLACKT 2 // number of stacked blocks to allow before we tpop them (in jtxdefn) - 0 means tpop every time - for T blocks
804805

805806
#define CWMAX 32766 // max # control words in an explicit defn. Must fit in signed 15-bit value because we complement it in storage
806807
#define SWMAX 32767 // max # words in a sentence
807808
#define EXPWMAX 16777215 // max # words in an explicit defn
808809

809-
#define LOCALRA 0 // ra() local names during lookup - must be set, but perhaps we can make it an option in explicit def
810-
811810
// flags for jteformat
812811
#define EMSGE 0xff // the error-code part
813812
#define EMSGNOEVM 0x200 // set to suppress moving the terse message

jsrc/jtype.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -759,8 +759,8 @@ struct AD {
759759
#define ARNAMED ((I)1<<ARNAMEDX) // set in the rank of a named locale table. This bit is passed in the return from jtsyrd1
760760
// bit 1 not used
761761
// the rest of the flags apply only to local symbol tables
762-
#define ARLCLONEDX NMSHAREDX // 4 set if this is a cloned local symbol table (in which symbol numbers are invalid)
763-
#define ARLCLONED (1LL<<ARLCLONEDX) // set if this is a cloned local symbol table (in which symbol numbers are invalid)
762+
#define ARLCLONEDX NMSHAREDX // 4 set if this is a cloned local symbol table (in which symbol numbers are invalid); OR in a global table that suppresses the check for locally-defined names
763+
#define ARLCLONED (1LL<<ARLCLONEDX)
764764
#define ARHASACVX 3 // set if this local symbol table contains an ACV
765765
#define ARHASACV ((I)1<<ARHASACVX)
766766
#define ARLOCALTABLE 16 // Set in rank of all local symbol tables. This indicates that the first hashchain holds x/y info and should not be freed as a symbol
@@ -914,10 +914,10 @@ typedef DST* DC;
914914
#define STKNAMEDX 0
915915
#define STKNAMED ((I)1<<STKNAMEDX) // set if the address is the address of the arg (rather than of a tpop slot)
916916
#define ISSTKNAMED(w) ((I)(w)&STKNAMED) // is fa() required?
917-
#define STKFAOWEDX 1 // till we have !LOCALRA, STKFAOWED is the same as STKLOCAL
918-
#define STKFAOWED ((I)1<<STKFAOWEDX) // set in parser stack if value needs to be freed
919-
#define STKREFRESHRQDX 2 // till we have !LOCALRA, STKFAOWED is the same as STKLOCAL
920-
#define STKREFRESHRQD ((I)1<<STKREFRESHRQDX) // set in verb of a line 1-3 exec to indicate that tpop[aw] are stale and must be refreshed from the stack
917+
#define STKFAOWEDX 1 // set in parser stack if value had ra() performed when it was stacked (or if ra() was performed later while on the stack)
918+
#define STKFAOWED ((I)1<<STKFAOWEDX)
919+
#define STKREFRESHRQDX 2 // set in verb of a line 1-3 exec to indicate that tpop[aw] are stale and must be refreshed from the stack
920+
#define STKREFRESHRQD ((I)1<<STKREFRESHRQDX)
921921
#define SETSTKFAOWED(w) (A)((I)(w)|STKFAOWED)
922922
#define CLRSTKFAOWED(w) (A)((I)(w)&~STKFAOWED)
923923
#define ISSTKFAOWED(w) ((I)(w)&STKFAOWED) // is fa() required?

jsrc/p.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -621,16 +621,14 @@ rdglob: ; // here when we tried the buckets and failed
621621
if((pt0ecam&(NAMEBYVALUE>>(NAMEBYVALUEX-NAMEFLAGSX)))|((I)y&QCNOUN)){ // use value if noun or special name, or name_:
622622
if(unlikely((pt0ecam&(NAMEABANDON>>(NAMEBYVALUEX-NAMEFLAGSX))))){ // is name_:?
623623
// if name_:, go delete the name, leaving the value to be deleted later.
624-
#if !LOCALRA
625624
// If the value is local, we must ra it and any other local pointers on the stack
626625
if(!ISFAOWED(y)&&!ACISPERM(AC(QCWORD(y)))&&!(AFLAG(QCWORD(y))&AFSENTENCEWORD)){ // if the name has been raised already, all stacked copies have been protected. If PERMANENT or from the executing sentence, needs no protecting
627626
rapos(QCWORD(y),y); // ra() the new value first so that all args to undco have been ra()d
628627
PSTK *sk;
629-
// scan the stack to see if it is at large in the stack, setting FAOWED when it is. We don't call protectlocals because we need to protect just the one value and speed might matter
628+
// scan the stack to see if the new value is at large in the stack, setting FAOWED when it is. We don't call protectlocals because we need to protect just the one value and speed might matter
630629
// the stacked value might have been an unflagged non-NAMED result, but after we ra() it we must call it STKNAMED because only STKNAMED values get fa()d when they leave execution
631630
for(sk=stack;sk!=stackend1;++sk){if(QCWORD(y)==QCWORD(sk->a) && !ISSTKFAOWED(sk->a)){rapos(QCWORD(y),y); sk->a=SETSTKNAMEDFAOWED(sk->a);}} // if the value we want to use is stacked already, it must be marked non-abondoned
632631
}
633-
#endif
634632
FPSZSUFF(y=nameundco(jtinplace, QCWORD(*(volatile A*)queue), y), fa(QCWORD(y));)
635633
}else y=SYMVALTOFAOWED(y) ; // if global, mark to free later
636634
}else if(unlikely(QCPTYPE(y)==VALTYPENAMELESS)){
@@ -760,7 +758,7 @@ endname: ;
760758
if(likely((s=(L*)(I)(NAV(QCWORD(*(volatile A*)queue))->symx&~REPSGN4(SGNIF4(pt0ecam,LOCSYMFLGX+ARLCLONEDX))))!=0)){
761759
zval=QCWORD((SYMORIGIN+(I)s)->fval); // get value of symbol in primary table. There may be no value; that's OK
762760
}else{zval=QCWORD(jtprobelocal(jt,QCWORD(*(volatile A*)queue),jt->locsyms));}
763-
targc=LOCALRA?ACUC2:ACUC1; // since local values are not ra()d, they will have AC=1 if inplaceable. This will miss sparse values (which have been ra()d. which is OK
761+
targc=ACUC1; // since local values are not ra()d, they will have AC=1 if inplaceable. This will miss sparse values (which have been ra()d. which is OK
764762
}else{zval=QCWORD(probequiet(QCWORD(*(volatile A*)queue))); targc=ACUC2;} // global assignment, get slot address. Global names have been ra()d and have AC=2
765763
// to save time in the verbs (which execute more often than this assignment-parse), see if the assignment target is suitable for inplacing. Set zombieval to point to the value if so
766764
// We require flags indicate not read-only, and correct usecount: 1 if local, 2 if global since we have raised the count of this block already if it is named and to be operated on inplace; +1 if NJA to account for the mapping reference.

jsrc/pv.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ F1(jtvtrans){PROLOG(0053);A locsyms,y,z=0;I c,i,ttabi;TA ttab[NTTAB];
238238
RZ(y=vtokens(w)); // return AM bit0=monad
239239
I tmonad=AM(y);
240240
ttabi=c;
241-
RZ(locsyms=stcreate(2,40,0L,0L)); AR(locsyms)&=~ARLOCALTABLE; // not necessary to set global pointers; flag table so we don't switch to locsyms during assignment
241+
RZ(locsyms=stcreate(2,40,0L,0L)); AR(locsyms)^=ARLOCALTABLE+ARLCLONED; // not necessary to set global pointers; flag table so we don't switch to locsyms during assignment, and suppress the check for local definitions
242242
symbis(mnuvxynam[5],num(1),locsyms); if(!tmonad)symbis(mnuvxynam[4],num(1),locsyms);
243243
WITHMSGSOFF(z=jttparse(jt,y,locsyms,tmonad,0==i,ttab,&ttabi,c);)
244244
if(i&&!z)z=colon(num(4-tmonad),w);

jsrc/s.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -689,7 +689,8 @@ A jtprobequiet(J jt,A a){A g;
689689
R res;
690690
}
691691

692-
// assign symbol: assign name a in symbol table g to the value w (but g is ignored if a is a locative)
692+
// assign symbol: assign name a in symbol table g to the value w
693+
// g is always the current local or global symbol table (but g is ignored if a is a locative). If a is not a locative and g is a local table,
693694
// Result is 0 if error, otherwise low 2 bits are x1 = final assignment, 1x = local assignment, others garbage
694695
// flags set in jt: bit 0=this is a final assignment; bit 1 always 0
695696
I jtsymbis(J jt,A a,A w,A g){F2PREFIP;
@@ -701,7 +702,7 @@ I jtsymbis(J jt,A a,A w,A g){F2PREFIP;
701702
// It is safe to do the recursive-usecount change here as local, because the value cannot have been released to any other core. Similarly for
702703
// virtuals.
703704
// Find the internal code for the name to be assigned. Do this before we take the lock.
704-
I wt=AT(w);
705+
I wt=AT(w); I gr=AR(g); // type of w, rank-flags for g
705706
rifv(w); // must realize any virtual
706707
if(unlikely(((wt^AFLAG(w))&RECURSIBLE)!=0)){AFLAGORLOCAL(w,wt&RECURSIBLE) wt=(I)jtra(w,wt,(A)wt);} // make the block recursive (incr children if was nonrecursive). This does not affect the usecount of w itself.
707708

@@ -711,7 +712,8 @@ I jtsymbis(J jt,A a,A w,A g){F2PREFIP;
711712
C*s=1+m+NAV(a)->s; if(unlikely(anmf&NMILOC))g=locindirect(n-m-2,1+s,NAV(a)->bucketx);else g=stfindcre(n-m-2,s,NAV(a)->bucketx);
712713
}else{ // not locative assignment
713714

714-
if(g==jt->global){ // global assignment.
715+
// obsolete if(g==jt->global){ // global assignment.
716+
if(!(gr&ARLOCALTABLE+ARLCLONED)){ // global assignment, and the symbol table does not suppress the check for local names
715717
// check for non-locative global assignment to a locally-defined name. Give domain error and immediately eformat, since no one has a self for assignment
716718
// this test will usually have a positive bucketx and will not call probelocal. Unlikely that symx is present
717719
I localnexist=REPSGN(NAV(a)->bucketx|SGNIF(AR(jt->locsyms),ARNAMEADDEDX)); // 0 if bucketx nonneg (meaning name known but not locally assigned) AND no unknown name has been assigned: i. e. no local def ~0 otherwise
@@ -729,18 +731,18 @@ I jtsymbis(J jt,A a,A w,A g){F2PREFIP;
729731

730732
if(unlikely((((NAV(a)->flag&NMLOC+NMILOC+NMIMPLOC)-1)&SGNIF(FAV(w)->flag2,VF2NAMELESSX))<0))valtype=VALTYPENAMELESS; // nameless & non-locative, so indicate
731733
if(unlikely(jt->glock!=0))if(likely(FAV(w)->fgh[0]!=0)){FAV(w)->flag|=VLOCK;} // fn created in locked function is also locked
732-
if((AR(g)&ARLOCALTABLE)!=0)AR(g)|=ARHASACV; // if we assign a non-noun to a local table, note the fact so we will look them up
734+
if(unlikely(gr&ARLOCALTABLE))AR(g)|=ARHASACV; // if we assign a non-noun to a local table, note the fact so we will look them up there
733735
}
734736

735737
L *e; // the symbol we will use
736738
// we don't have e, look it up.
737739
// We reserve 1 symbol for the new name, in case the name is not defined. If the name is not new we won't need the symbol.
738740
// convert valtype to QCSYMVAL semantics: NAMED always, RAREQD if global table or sparse
739-
if((AR(g)&ARLOCALTABLE)!=0){ // if assignment to a local table (which might not be jt->locsyms)
741+
if((gr&ARLOCALTABLE)!=0){ // if assignment to a local table (which might not be jt->locsyms)
740742
I4 symx=NAV(a)->symx; // fetch the symbol slot assigned to this name (0 if none)
741-
e=likely((SGNIF(AR(g),ARLCLONEDX)|(symx-1))>=0)?SYMORIGIN+(I)symx:probeislocal(a,g); // local symbol given and we are using the original table: use the symbol. Otherwise, look up and reserve 1 symbol
743+
e=likely((SGNIF(gr,ARLCLONEDX)|(symx-1))>=0)?SYMORIGIN+(I)symx:probeislocal(a,g); // local symbol given and we are using the original table: use the symbol. Otherwise, look up and reserve 1 symbol
742744
g=(A)((I)jtinplace|-JTASGNWASLOCAL); // indicate local assignment (we have no lock to clear), remember final assignment
743-
valtype|=QCNAMED|(LOCALRA?QCRAREQD:REPSGN(wt)&QCRAREQD); // enter QCSYMVAL semantics; ra needed if sparse
745+
valtype|=QCNAMED|(REPSGN(wt)&QCRAREQD); // enter QCSYMVAL semantics; ra needed if sparse
744746
}else{ // global table
745747
SYMRESERVE(1) // before we go into lock, make sure we have a symbol to assign to
746748
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

jsrc/va2.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,7 +1248,7 @@ DF2(jtfslashatg){A fs,gs,y,z;B b;C*av,*wv;I ak,an,ar,*as,at,m,
12481248
DF2(jtatomic2){A z;
12491249
F2PREFIP;ARGCHK2(a,w);
12501250
UI ar=AR(a), wr=AR(w); I at=AT(a), wt=AT(w); I af;
1251-
if((ar+wr+((at|wt)&((NOUN|SPARSE)&~(B01+INT+FL))))==0){af=0; goto forcess;} // if args are both atoms, verb rank is immaterial - run as singleton
1251+
if((ar+wr+((at|wt)&((NOUN|SPARSE)&~(B01+INT+FL))))==0){af=0; goto forcess;} // if args are both INT/FL/B01 atoms, verb rank is immaterial - run as singleton
12521252
A realself=FAV(self)->fgh[0]; // if rank operator, this is nonzero and points to the left arg of rank
12531253
RANK2T selfranks=FAV(self)->lrr; // get left & right rank from rank/primitive
12541254
self=realself?realself:self; // if this is a rank block, move to the primitive to get to the function pointers. u b. or any atomic primitive has f clear
@@ -1288,7 +1288,8 @@ forcess:; // branch point for rank-0 singletons from above, always with atomic
12881288
selfranks=jtranks==R2MAX?selfranks:jtranks;
12891289
}
12901290
// self, awr, and selfranks are needed in the retry
1291-
}
1291+
}
1292+
// not singleton, or singleton needing retry
12921293

12931294
ASSERTAGREE(AS(a),AS(w),af); // outermost (or only) agreement check
12941295
NOUNROLL while(1){

jsrc/x.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -380,8 +380,8 @@ MN(18,7) XPRIM(VERB, jtsetpermanent, 0, VFLAGNONE,VF2NONE,RMAX,RMAX,RM
380380

381381
// 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
382382
I jtforeignassigninit(J jt){A nm;L *e;
383-
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;
384-
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;
383+
RZ(nm=nfs(12,"cocurrent_z_")); symbis(nm,(A)&foreignA[(sizeof(foreignA)/sizeof(foreignA[0]))-1],jt->global); e=probeisres(nm, *JT(jt,zpath)); e->flag|=LREADONLY; // the assignment is in z, but we need...
384+
RZ(nm=nfs(10,"coclass_z_")); symbis(nm,(A)&foreignA[(sizeof(foreignA)/sizeof(foreignA[0]))-1],jt->global); e=probeisres(nm, *JT(jt,zpath)); e->flag|=LREADONLY; // ... a valid global table as an arg
385385
R 1;
386386
}
387387

jsrc/xt.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ foundsym:; // we found the symbol. Install its info. sym is the symbol, SYMNE
285285
A *old=jt->tnextpushp;
286286
t=qpc(); // start time
287287
// We attempt to run as if under jtxdefn, so we check ATTN and jt->jerr as a replacement for reading from the word block; and we tpop like jtxdefn
288-
DQ(n, z=PARSERVALUE(parsea(wv,wn)); if(unlikely(!z))break; ASSERT((__atomic_load_n((S*)JT(jt,adbreakr),__ATOMIC_ACQUIRE)&3)==0,EVATTN) RE(0) if((UI)jt->tnextpushp-(UI)old>TPOPSLACK*SZI)tpop(old););
288+
DQ(n, z=PARSERVALUE(parsea(wv,wn)); if(unlikely(!z))break; ASSERT((__atomic_load_n((S*)JT(jt,adbreakr),__ATOMIC_ACQUIRE)&3)==0,EVATTN) RE(0) if((UI)jt->tnextpushp-(UI)old>TPOPSLACKB*SZI)tpop(old););
289289
t=qpc()-t; // Run the sentence. No need to run as exec since the result doesn't escape. tpop like jtxdefn. no tpop on error.
290290
if(unlikely(stackallo))debz();
291291
RZ(z); // if error, fail the timing request

test/g4x.ijs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,15 +220,18 @@ b =: 7!:0''
220220
1e6 1e6 -: (# a_:) , # a NB. deleted, stack deferred
221221
b > 2e6+7!:0''
222222
'value error' -: ". etx 'a + 5'
223+
223224
1 -: 3 : 0 ''
224225
a =. i. 1e6
225226
b =. 7!:0''
226227
assert. 1e6 -: # a_:
228+
for. i. 6 do. b end.
227229
assert. b > 2e6+7!:0''
228230
assert. 'value error' -: ". etx 'a + 5'
229231
a =. i. 1e6
230232
b =. 7!:0''
231233
assert. 1e6 -: ". '# a_:' NB. not deleted inside ".
234+
for. i. 6 do. b end.
232235
assert. b < 1e6+7!:0''
233236
assert. 1e6 -: # a
234237
a =. i. 1e6
@@ -240,6 +243,7 @@ assert. 2e6 -: # a_: , a NB. deleted, stack deferred
240243
a =. i. 1e6
241244
b =. 7!:0''
242245
assert. 1e6 1e6 -: (# a_:) , , # a NB. deleted, stack deferred
246+
for. i. 6 do. b end.
243247
assert. b > 2e6+7!:0''
244248
assert. 'value error' -: ". etx 'a + 5'
245249
a =. 1

0 commit comments

Comments
 (0)