Skip to content

Commit 5405071

Browse files
committed
Parsing tweaks for name lookup
1 parent 1816fbe commit 5405071

3 files changed

Lines changed: 25 additions & 22 deletions

File tree

jsrc/jtype.h

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -583,11 +583,12 @@ typedef I SI;
583583

584584
// Flags in the AR field of symbol tables
585585
#define ARNAMED 1 // set in the rank of a named locale table. This bit is passed in the return from jtsyrd1
586-
#define ARNAMEADDED LPERMANENT // Set in rank when a new name is added to the local symbol table. We transfer the bit from the L flags to the rank-flag
586+
#define ARNAMEADDEDX LPERMANENTX // 2 Set in rank when a new name is added to the local symbol table. We transfer the bit from the L flags to the rank-flag
587+
#define ARNAMEADDED (1LL<<ARNAMEADDEDX) // set if this is a cloned local symbol table (in which symbol numbers are invalid)
588+
#define ARLCLONEDX NMSHAREDX // 4 set if this is a cloned local symbol table (in which symbol numbers are invalid)
589+
#define ARLCLONED (1LL<<ARLCLONEDX) // set if this is a cloned local symbol table (in which symbol numbers are invalid)
587590
#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
588591
#define ARLSYMINUSE 32 // This bit is set in the rank of the original symbol table when it is in use
589-
#define ARLCLONEDX NMSHAREDX // set if this is a cloned local symbol table (in which symbol numbers are invalid)
590-
#define ARLCLONED (1LL<<ARLCLONEDX) // set if this is a cloned local symbol table (in which symbol numbers are invalid)
591592

592593
#define SFNSIMPLEONLY 1 // to sfn: return simple name only, discarding any locative
593594

@@ -695,9 +696,10 @@ typedef struct {
695696
// In all local symbol tables, the first 'hashchain' has the chain numbers for y/x; they are the first symbols in those chains, always permanent
696697

697698
#define LCH (I)1 /* changed since last exec of 4!:5 */
698-
#define LCACHED (I)2 // this value is cached in some nameref
699+
#define LPERMANENTX 1
700+
#define LPERMANENT ((I)1<<LPERMANENTX) // set if the name was assigned from an abandoned value, and we DID NOT raise the usecount of the value (we will have changed INPLACE to ACUC1, though).
699701
#define LINFO (I)4 /* locale info */
700-
#define LPERMANENT (I)8 // This is a permanent entry in a local symbol table; don't delete, just leave val=0
702+
#define LCACHED (I)8 // this value is cached in some nameref
701703
#define LWASABANDONEDX 4
702704
#define LWASABANDONED ((I)1<<LWASABANDONEDX) // set if the name was assigned from an abandoned value, and we DID NOT raise the usecount of the value (we will have changed INPLACE to ACUC1, though).
703705
// when the name is reassigned or deleted, we must refrain from fa(), and if the value still has AC=ACUC1, we should revert it to inplaceable so that the parser will free it
@@ -757,16 +759,16 @@ typedef struct{
757759

758760
// values in flag:
759761
#define NMLOC 1 // direct locale abc_lm_ only one of NMLOC/NMILOC/NMIMPLOC is set
762+
#define NMSHAREDX 2
763+
#define NMSHARED (1LL<<NMSHAREDX) // This NM is for a locally-defined name and is shared by all references to the name
760764
#define NMILOC 2 // indirect locale abc__de__fgh ... only one of NMLOC/NMILOC/NMIMPLOC is set
761-
#define NMDOT 4 // one of the names m. n. u. v. x. y. */
765+
#define NMDOT 128 // one of the names m. n. u. v. x. y. */
762766
#define NMXY 8 // x/y, which must have NAMEBYVALUE set
763767
#define NMIMPLOC 16 // this NM block is u./v. only one of NMLOC/NMILOC/NMIMPLOC is set
764768
#define NMCACHEDX 5
765769
#define NMCACHED (1LL<<NMCACHEDX) // This NM is to cache any valid lookup
766770
#define NMCACHEDSYMX 6
767771
#define NMCACHEDSYM (1<<NMCACHEDSYMX) // This NM is storing a symbol index, not a pointer to a reference
768-
#define NMSHAREDX 7
769-
#define NMSHARED (1LL<<NMSHAREDX) // This NM is for a locally-defined name and is shared by all references to the name
770772

771773

772774
typedef struct {I a,e,i,x;} P;

jsrc/p.c

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ static A virthook(J jtip, A f, A g){
342342
// name:: delete the symbol name but not deleting the value. If the usecount of the value is 1 and it is not on the NVR stack, make it inplaceable. Replace the nameref with a tpush or NVR free
343343
static I namecoco(J jt, A y, I at, LX *locbuckets, L *s, A sv, L *sympv){F1PREFIP;
344344
if(((I)jtinplace&JTFROMEXEC))R 1;
345-
A fndst=UNLXAV0(locbuckets); if(unlikely((at&VERB)!=0))fndst=syrdforlocale(y); // get locale to use. This re-looks up global names, but they should be rare in name::
345+
A fndst=UNLXAV0((LX *)((I)locbuckets&-8)); if(unlikely((at&VERB)!=0))fndst=syrdforlocale(y); // get locale to use. This re-looks up global names, but they should be rare in name::
346346
LX *asymx=LXAV0(fndst)+SYMHASH(NAV(s->name)->hash,AN(fndst)-SYMLINFOSIZE); // get pointer to index of start of chain; address of previous symbol in chain
347347
LX nextsymx=*asymx; // symbol number pointed to by asymx, possibly w/permanent indicator
348348
while(sympv+SYMNEXT(nextsymx)!=s){asymx=&(sympv+SYMNEXT(nextsymx))->next; nextsymx=*asymx;}
@@ -491,9 +491,10 @@ A jtparsea(J jt, A *queue, I nwds){F1PREFIP;PSTK * RESTRICT stack;A z,*v;
491491
// debugging jt->parsercalls=0xdd;
492492
// DO NOT RETURN from inside the parser loop. Stacks must be processed.
493493
LX *locbuckets=LXAV0(jt->locsyms); // the local symbol table cannot change during the parse
494-
// Move rank flags from locsyms to locbuckets low bits. NOTE that locbuckets is always on an 8-byte boundary, even in 32-bit code
495-
494+
// Move rank flags from locsyms to locbuckets low bits. NOTE that locbuckets is always on an 8-byte boundary, even in 32-bit code. Flag bits are 1-2
495+
locbuckets=(LX *)((I)locbuckets+(AR(jt->locsyms)&(ARLCLONED|ARNAMEADDED)));
496496
UI4 stack0pt=PTMARK; // will hold the EDGE+AVN value, which doesn't change much and is stored late someday combine this with mes (64-bit only)
497+
// One of the bits of locbuckets gets moved to a register here, so we know register pressure isn't great
497498
while(1){ // till no more matches possible...
498499

499500
// no executable fragment, pull from the queue. If we pull ')', there is no way we can execute
@@ -524,22 +525,22 @@ A jtparsea(J jt, A *queue, I nwds){F1PREFIP;PSTK * RESTRICT stack;A z,*v;
524525
// To save some overhead, we inline this and do the analysis in a different order here
525526
// The important performance case is local names with bucket info. Pull that out & do it without the call overhead
526527
// This code is copied from s.c, except for the symx: since that occurs only in explicit definitions we can get to it only through here
527-
I locstflags=AR(UNLXAV0(locbuckets)); // flags from local symbol table
528-
L *sympv=JT(jt,sympv);
529-
if(likely((SGNIF(locstflags,ARLCLONEDX)|(NAV(y)->symx-1))>=0)){ // if we are using primary table and there is a symbol stored there...
528+
// obsolete I locstflags=AR(UNLXAV0(locbuckets)); // flags from local symbol table
529+
L *sympv=JT(jt,sympv); // symbol root can change during parse, but not during stacking of a single execution
530+
if(likely((SGNIF(locbuckets,ARLCLONEDX)|(NAV(y)->symx-1))>=0)){ // if we are using primary table and there is a symbol stored there...
530531
s=sympv+(I)NAV(y)->symx; // get address of symbol in primary table
531532
if(unlikely((sv=s->val)==0))goto rdglob; // if value has not been assigned, ignore it
532533
}else if(likely(NAV(y)->bucket!=0)){I bx;
533534
if(likely(0 <= (bx = ~NAV(y)->bucketx))){ // negative bucketx (now positive); skip that many items, and then you're at the right place. This is the path for almost all local symbols
534-
s = locbuckets[NAV(y)->bucket]+sympv; // fetch hashchain headptr, point to L for first symbol
535+
s = ((LX *)((I)locbuckets&-8))[NAV(y)->bucket]+sympv; // fetch hashchain headptr, point to L for first symbol
535536
if(unlikely(bx>0)){NOUNROLL do{s = s->next+sympv;}while(--bx);} // skip the prescribed number, which is usually 1
536537
if(unlikely((sv=s->val)==0))goto rdglob; // if value has not been assigned, ignore it
537538
}else{
538539
// positive bucketx (now negative); that means skip that many items and then do name search. This is set for words that were recognized as names but were not detected as assigned-to in the definition. This is the path for global symbols
539540
// If no new names have been assigned since the table was created, we can skip this search, since it must fail (this is the path for words in z eg)
540-
if(likely(!(locstflags&ARNAMEADDED)))goto rdglob;
541+
if(likely(!((I)locbuckets&ARNAMEADDED)))goto rdglob;
541542
// from here on it is rare to find a name - usually they're globals defined elsewhere
542-
LX lx = locbuckets[NAV(y)->bucket]; // index of first block if any
543+
LX lx = ((LX *)((I)locbuckets&-8))[NAV(y)->bucket]; // index of first block if any
543544
I m=NAV(y)->m; C* nm=NAV(y)->s; UI4 hsh=NAV(y)->hash; // length/addr of name from name block
544545
if(unlikely(++bx!=0)){NOUNROLL do{lx = sympv[lx].next;}while(++bx);} // rattle off the permanents, usually 1
545546
// Now lx is the index of the first name that might match. Do the compares
@@ -582,8 +583,8 @@ rdglob: ; // here when we tried the buckets and failed
582583
AAV1(jt->nvra)[jt->parserstackframe.nvrtop++] = sv; // record the place where the value was protected, so we can free it when this sentence completes
583584
} // if NJA/virtual, leave NVR alone
584585
}
585-
}else goto undefname;
586-
}else goto undefname;
586+
}else goto undefname; // no val
587+
}else goto undefname; // no sym
587588
at|=VERB; // indicate that the symbol was not in the local table
588589
}
589590
// end of looking at local/global symbol tables
@@ -699,10 +700,10 @@ endname: ;
699700
if((UI)(pline>>VJTFLGOK1X)>(UI)PTISNOTASGNNAME(stack[0]))if(likely(PTISM(stackfs[2]))){L *s; // assignment to name; nothing in the stack to the right of what we are about to execute; well-behaved function (doesn't change locales)
700701
if(likely((AT(stack[0].a))&ASGNLOCAL)){
701702
// local assignment. To avoid subroutine call overhead, make a quick check for primary symbol
702-
if(likely((SGNIF(AR(UNLXAV0(locbuckets)),ARLCLONEDX)|(NAV(queue[mes-1])->symx-1))>=0)){ // if we are using primary table and there is a symbol stored there...
703+
if(likely((SGNIF(locbuckets,ARLCLONEDX)|(NAV(queue[mes-1])->symx-1))>=0)){ // if we are using primary table and there is a symbol stored there...
703704
s=JT(jt,sympv)+(I)NAV(queue[mes-1])->symx; // get address of symbol in primary table. There may be no value; that's OK
704705
}else{s=jtprobeislocal(jt,queue[mes-1]);}
705-
}else s=jtprobeisquiet(jt,queue[mes-1],UNLXAV0(locbuckets)); // global assignment, get slot address
706+
}else s=jtprobeisquiet(jt,queue[mes-1],UNLXAV0((LX *)((I)locbuckets&-8))); // global assignment, get slot address
706707
// Don't remember the assignand if it may change during execution, i. e. if the verb is unsafe. For line 1 we have to look at BOTH verbs that come after the assignment
707708
// obsolete s=((FAV(fs)->flag&(FAV(stack[1].a)->flag|((~pmask)<<(VASGSAFEX-1))))&VASGSAFE)?s:0;
708709
s=((FAV(fs)->flag&(FAV(stack[1].a)->flag|((~pline)<<VASGSAFEX)))&VASGSAFE)?s:0; // pline is 0-2; if not 1, ignore 2nd stkpos

test/g18x.ijs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ NB. Flag is changed,cachable,LINFO,PERM,WASABANDONED,hasname,hasvalue
6262
f =. 2{"1 p
6363
NB. pfst =. 2<:4|f NB. symbol is in pfst, may have no value
6464
li=. 4<:8|f NB. locale info
65-
perm=. 8<:16|f NB. permanent
65+
perm=. 2<:4|f NB. permanent
6666
assert. i -: 0{"1 p NB. index
6767
assert. b +. li +. ((1{"1 p)e.oktypes) +. (perm *. 0 = 1{"1 p) NB. internal type
6868
assert. li <: (s e.<'**local**')+.0 32 e.~ 1{"1 p NB. search path of locales - 0 if local symbol table

0 commit comments

Comments
 (0)