Skip to content

Commit 7071d11

Browse files
committed
Shorter FAOWED processing
1 parent 180080f commit 7071d11

File tree

2 files changed

+37
-23
lines changed

2 files changed

+37
-23
lines changed

jsrc/p.c

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -887,7 +887,7 @@ RECURSIVERESULTSCHECK
887887
AF actionfn=__atomic_load_n(&FAV(fs)->valencefns[pmask-1],__ATOMIC_RELAXED); // refetch the routine address early. This may chain 2 fetches, which finishes about when the indirect branch is executed
888888
A arg1=stack[1].a; // 1st arg, monad or left dyad
889889
A arg2=stack[pmask+1].a; // 2nd arg, fs or right dyad
890-
A arg3=__atomic_load_n(&stack[2].a,__ATOMIC_RELAXED); arg3=pmask&2?arg3:(A)jt; // fs, if this is a conjunction, for FAOWED testing. If not conj, set to jt which has FAOWED clear but allows reads. Atomic to avoid branch
890+
A arg3=__atomic_load_n(&stack[2].a,__ATOMIC_RELAXED); arg3=pmask&2?arg3:0; // fs, if this is a conjunction, for FAOWED testing. If not conj, set to 0 which has FAOWED clear. Atomic to avoid branch
891891
UI4 restok=stack[1].t; // save token # to use for result
892892
// We set the MODIFIER flag in the call so that jtxdefn/unquote can know that they are modifiers
893893
// We mark the inputs inplaceable (the first modifier to support that is u`v) - both always, even for adverbs
@@ -911,12 +911,17 @@ RECURSIVERESULTSCHECK
911911
// Make sure the result is recursive. We need this to guarantee that any named value that has been incorporated has its usecount increased,
912912
// so that it is safe to remove its protection
913913
ramkrecursv(yy); // force recursive y
914-
A freep=stack[1].a;
915-
if(ISSTKFAOWED(freep)){freep=QCWORD(freep);if(unlikely(freep==yy))yy=SETSTKFAOWED(yy);else faowed(freep,__atomic_load_n(&AC(QCWORD(freep)),__ATOMIC_RELAXED),__atomic_load_n(&AT(QCWORD(freep)),__ATOMIC_RELAXED));}
916-
freep=stack[pmask+1].a;
917-
if(ISSTKFAOWED(freep)){freep=QCWORD(freep);if(unlikely(freep==yy))yy=SETSTKFAOWED(yy);else faowed(freep,__atomic_load_n(&AC(QCWORD(freep)),__ATOMIC_RELAXED),__atomic_load_n(&AT(QCWORD(freep)),__ATOMIC_RELAXED));}
918-
freep=arg3;
919-
if(ISSTKFAOWED(freep)){freep=QCWORD(freep);if(unlikely(freep==yy))yy=SETSTKFAOWED(yy);else faowed(freep,__atomic_load_n(&AC(QCWORD(freep)),__ATOMIC_RELAXED),__atomic_load_n(&AT(QCWORD(freep)),__ATOMIC_RELAXED));}
914+
915+
while(1){ // for each stacked value, free the value unless it survives to the result, in which case it inherits the FAOWED. Only one FAOWED can be passed on this way
916+
if(ISSTKFAOWED(arg1)){if(unlikely(QCWORD(arg1)==yy))yy=arg1;else faowed(QCWORD(arg1),__atomic_load_n(&AC(QCWORD(arg1)),__ATOMIC_RELAXED),__atomic_load_n(&AT(QCWORD(arg1)),__ATOMIC_RELAXED));}
917+
if(arg2==0)break; arg1=arg2; arg2=arg3; arg3=0;
918+
};
919+
// obsolete A freep=stack[1].a;
920+
// obsolete if(ISSTKFAOWED(freep)){freep=QCWORD(freep);if(unlikely(freep==yy))yy=SETSTKFAOWED(yy);else faowed(freep,__atomic_load_n(&AC(QCWORD(freep)),__ATOMIC_RELAXED),__atomic_load_n(&AT(QCWORD(freep)),__ATOMIC_RELAXED));}
921+
// obsolete freep=stack[pmask+1].a;
922+
// obsolete if(ISSTKFAOWED(freep)){freep=QCWORD(freep);if(unlikely(freep==yy))yy=SETSTKFAOWED(yy);else faowed(freep,__atomic_load_n(&AC(QCWORD(freep)),__ATOMIC_RELAXED),__atomic_load_n(&AT(QCWORD(freep)),__ATOMIC_RELAXED));}
923+
// obsolete freep=arg3;
924+
// obsolete if(ISSTKFAOWED(freep)){freep=QCWORD(freep);if(unlikely(freep==yy))yy=SETSTKFAOWED(yy);else faowed(freep,__atomic_load_n(&AC(QCWORD(freep)),__ATOMIC_RELAXED),__atomic_load_n(&AT(QCWORD(freep)),__ATOMIC_RELAXED));}
920925

921926
y=NEXTY; // refetch next-word to save regs
922927
stack[pmask]=stack[0]; // close up the stack
@@ -934,7 +939,7 @@ RECURSIVERESULTSCHECK
934939
A symtab=jt->locsyms; {A gsyms=jt->global; symtab=!EXPLICITRUNNING?gsyms:symtab; symtab=!(stack[1].pt&PTASGNLOCAL)?gsyms:symtab;} // use global table if =: used, or symbol table is the short one, meaning 'no symbols'
935940
I rc;
936941
if(likely(GETSTACK0PT&PTNAME0))rc=jtsymbis((J)((I)jt|(((US)pt0ecam==0)<<JTFINALASGNX)),QCWORD(stack[0].a),QCWORD(stack[2].a),symtab); // Assign to the known name. If ASSIGNSYM is set, PTNAME0 must also be set
937-
else rc=jtis((J)((I)jt|(((US)pt0ecam==0)<<JTFINALASGNX)),QCWORD(stack[0].a),QCWORD(stack[2].a),symtab);
942+
else rc=jtis((J)((I)jt|(((US)pt0ecam==0)<<JTFINALASGNX)),QCWORD(stack[0].a),QCWORD(stack[2].a),symtab); // unknown or multiple name, process
938943
#if MEMAUDIT&0x10
939944
auditmemchains();
940945
#endif
@@ -967,12 +972,17 @@ RECURSIVERESULTSCHECK
967972
RECURSIVERESULTSCHECK
968973
ramkrecursv(yy); // force recursive y
969974
y=NEXTY; // refetch next-word to save regs
970-
A freep=stack[1].a;
971-
if(ISSTKFAOWED(freep)){freep=QCWORD(freep);if(unlikely(freep==yy))yy=SETSTKFAOWED(yy);else faowed(freep,__atomic_load_n(&AC(QCWORD(freep)),__ATOMIC_RELAXED),__atomic_load_n(&AT(QCWORD(freep)),__ATOMIC_RELAXED));}
972-
freep=stack[2].a;
973-
if(ISSTKFAOWED(freep)){freep=QCWORD(freep);if(unlikely(freep==yy))yy=SETSTKFAOWED(yy);else faowed(freep,__atomic_load_n(&AC(QCWORD(freep)),__ATOMIC_RELAXED),__atomic_load_n(&AT(QCWORD(freep)),__ATOMIC_RELAXED));}
974-
freep=stack[3].a;
975-
if(ISSTKFAOWED(freep)){freep=QCWORD(freep);if(unlikely(freep==yy))yy=SETSTKFAOWED(yy);else faowed(freep,__atomic_load_n(&AC(QCWORD(freep)),__ATOMIC_RELAXED),__atomic_load_n(&AT(QCWORD(freep)),__ATOMIC_RELAXED));}
975+
while(1){ // for each stacked value, free the value unless it survives to the result, in which case it inherits the FAOWED. Only one FAOWED can be passed on this way
976+
if(ISSTKFAOWED(arg1)){if(unlikely(QCWORD(arg1)==yy))yy=arg1;else faowed(QCWORD(arg1),__atomic_load_n(&AC(QCWORD(arg1)),__ATOMIC_RELAXED),__atomic_load_n(&AT(QCWORD(arg1)),__ATOMIC_RELAXED));}
977+
if(arg2==0)break; arg1=arg2; arg2=arg3; arg3=0;
978+
};
979+
980+
// obsolete A freep=stack[1].a;
981+
// obsolete if(ISSTKFAOWED(freep)){freep=QCWORD(freep);if(unlikely(freep==yy))yy=SETSTKFAOWED(yy);else faowed(freep,__atomic_load_n(&AC(QCWORD(freep)),__ATOMIC_RELAXED),__atomic_load_n(&AT(QCWORD(freep)),__ATOMIC_RELAXED));}
982+
// obsolete freep=stack[2].a;
983+
// obsolete if(ISSTKFAOWED(freep)){freep=QCWORD(freep);if(unlikely(freep==yy))yy=SETSTKFAOWED(yy);else faowed(freep,__atomic_load_n(&AC(QCWORD(freep)),__ATOMIC_RELAXED),__atomic_load_n(&AT(QCWORD(freep)),__ATOMIC_RELAXED));}
984+
// obsolete freep=stack[3].a;
985+
// obsolete if(ISSTKFAOWED(freep)){freep=QCWORD(freep);if(unlikely(freep==yy))yy=SETSTKFAOWED(yy);else faowed(freep,__atomic_load_n(&AC(QCWORD(freep)),__ATOMIC_RELAXED),__atomic_load_n(&AT(QCWORD(freep)),__ATOMIC_RELAXED));}
976986
stack[3].t = stack[1].t; stack[3].a = yy; // take err tok from f; save result; no need to set parsertype, since it didn't change
977987
stack[2]=stack[0]; stack+=2; // close up stack
978988
}else{
@@ -989,12 +999,16 @@ RECURSIVERESULTSCHECK
989999
// errors inside hook are formatted there. The only error on the hook itself is syntax, for which the terse error is enough
9901000
RECURSIVERESULTSCHECK
9911001
ramkrecursv(yy); // force recursive y
992-
A freep=stack[1].a;
993-
if(ISSTKFAOWED(freep)){freep=QCWORD(freep);if(unlikely(freep==yy))yy=SETSTKFAOWED(yy);else faowed(freep,__atomic_load_n(&AC(QCWORD(freep)),__ATOMIC_RELAXED),__atomic_load_n(&AT(QCWORD(freep)),__ATOMIC_RELAXED));}
994-
freep=stack[2].a;
995-
if(ISSTKFAOWED(freep)){freep=QCWORD(freep);if(unlikely(freep==yy))yy=SETSTKFAOWED(yy);else faowed(freep,__atomic_load_n(&AC(QCWORD(freep)),__ATOMIC_RELAXED),__atomic_load_n(&AT(QCWORD(freep)),__ATOMIC_RELAXED));}
996-
freep=arg3;
997-
if(ISSTKFAOWED(freep)){freep=QCWORD(freep);if(unlikely(freep==yy))yy=SETSTKFAOWED(yy);else faowed(freep,__atomic_load_n(&AC(QCWORD(freep)),__ATOMIC_RELAXED),__atomic_load_n(&AT(QCWORD(freep)),__ATOMIC_RELAXED));}
1002+
while(1){ // for each stacked value, free the value unless it survives to the result, in which case it inherits the FAOWED. Only one FAOWED can be passed on this way
1003+
if(ISSTKFAOWED(arg1)){if(unlikely(QCWORD(arg1)==yy))yy=arg1;else faowed(QCWORD(arg1),__atomic_load_n(&AC(QCWORD(arg1)),__ATOMIC_RELAXED),__atomic_load_n(&AT(QCWORD(arg1)),__ATOMIC_RELAXED));}
1004+
if(arg2==mark)break; arg1=arg2; arg2=arg3; arg3=mark;
1005+
};
1006+
// obsolete A freep=stack[1].a;
1007+
// obsolete if(ISSTKFAOWED(freep)){freep=QCWORD(freep);if(unlikely(freep==yy))yy=SETSTKFAOWED(yy);else faowed(freep,__atomic_load_n(&AC(QCWORD(freep)),__ATOMIC_RELAXED),__atomic_load_n(&AT(QCWORD(freep)),__ATOMIC_RELAXED));}
1008+
// obsolete freep=stack[2].a;
1009+
// obsolete if(ISSTKFAOWED(freep)){freep=QCWORD(freep);if(unlikely(freep==yy))yy=SETSTKFAOWED(yy);else faowed(freep,__atomic_load_n(&AC(QCWORD(freep)),__ATOMIC_RELAXED),__atomic_load_n(&AT(QCWORD(freep)),__ATOMIC_RELAXED));}
1010+
// obsolete freep=arg3;
1011+
// obsolete if(ISSTKFAOWED(freep)){freep=QCWORD(freep);if(unlikely(freep==yy))yy=SETSTKFAOWED(yy);else faowed(freep,__atomic_load_n(&AC(QCWORD(freep)),__ATOMIC_RELAXED),__atomic_load_n(&AT(QCWORD(freep)),__ATOMIC_RELAXED));}
9981012
y=NEXTY; // refetch next-word to save regs
9991013
PTFROMTYPE(stack[trident].pt,AT(QCWORD(yy))) stack[trident].t = stack[trident-1].t; stack[trident].a = yy; // take err tok from f of hook, g of trident; save result. Must store new type because this line takes adverb hooks also
10001014
stack[trident-1]=stack[0]; stack+=trident-1; // close up stack
@@ -1110,10 +1124,10 @@ abandname:;
11101124
// If the value is local, we must ra it.
11111125
if(unlikely(!ISGLOBAL(sv)))rapos(QCWORD(sv),sv); // ra() the new value first
11121126
#endif
1113-
sv=nameundco(jtinplace, y, sv); // if name_:, go delete the name, leaving the value to be deleted later. sv has QCFAOWED semantics
1127+
sv=nameundco(jtinplace, y, sv); // if name_:, go delete the name, leaving the value to be deleted later. returned sv has QCFAOWED semantics
11141128
y=QCWORD(sv); sv=(A)ISFAOWED(sv); // undco will set FAOWED if it didn't fa() the value; transfer that to sv
11151129
}else{y=QCWORD(sv); if(!LOCALRA)sv=(A)ISGLOBAL(sv);} // not name_:, just use the value. sv=non0 if it needs free
1116-
}else{y=QCWORD(namerefacv(y, sv)); sv=0;} // Replace other acv with reference. Could fail. Undo the ra from syrd if global
1130+
}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
11171131
}else{
11181132
// undefined name. This is very subtle. We will return a reference to [: as required by the rules (User might execute ".'undefname' which should return empty with no error).
11191133
// This will be formatted for error, if ever, only when returning the value to console level - but at that point the failing sentence has been lost. That will be OK because ASSERTN

jsrc/vcat.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ static C*jtovgmove(J jt,I k,I c,I m,A s,A w,C*x,I somefill){I d,n,p=c*m; // p=#
113113
// z may not be boxed; but if it is, w must be also.
114114
if(AR(w)){
115115
n=AN(w); d=AN(s)-AR(w);
116-
if((~somefill|(-n&(d-1)))>=0)mvc(k*p,x,k,jt->fillv); // fill required: w empty or shape short (d>0)
116+
if((~somefill|(-n&(d-1)))>=0)mvc(k*p,x,k,jt->fillv); // fill required: w empty or shape short (d>0). Fills unnecessarily if axis was extended with 1s and the other arg needed fill
117117
if(n){ // nonempty cell, must copy in the data
118118
if(n<p){I *v=AV(s); *v=m; RZ(w=take(d?vec(INT,AR(w),d+v):s,w));} // incoming cell smaller than result area: take to result-cell size (uses fill)
119119
JMC(x,AV(w),k*AN(w),1); // copy in the data, now the right cell shape but possibly shorter than the fill kludge could avoid double copy

0 commit comments

Comments
 (0)