/* Access events are primary evidence; snapshots are only the replay oracle. */ #include "context_access_diag.h" #include #include #include static FILE *ax_file; static NativePropertyCache *ax_cache; static NativePipeCache *ax_pipes; static int ax_active,ax_pending; static unsigned long long ax_id; static void hex(const void *p,size_t n){const unsigned char *b=p;for(size_t i=0;icount); blob("context",ax_cache,sizeof(*ax_cache));fputc(',',ax_file); blob("states",ax_cache->states,ax_cache->count*sizeof(*ax_cache->states));fputc(',',ax_file); blob("pipes",ax_pipes,40*sizeof(*ax_pipes));fputs("}\n",ax_file); } static int locate(const void *ptr,size_t n,const char **domain,size_t *offset){ uintptr_t p=(uintptr_t)ptr; const void *bases[]={ax_cache,ax_cache?ax_cache->states:NULL,ax_pipes}; size_t sizes[]={sizeof(*ax_cache),ax_cache?ax_cache->capacity*sizeof(*ax_cache->states):0,40*sizeof(*ax_pipes)}; const char *names[]={"context","states","pipes"}; for(int i=0;i<3;i++)if(bases[i] && p>=(uintptr_t)bases[i] && p-(uintptr_t)bases[i]+n<=sizes[i]){ *domain=names[i];*offset=p-(uintptr_t)bases[i];return 1; } return 0; } void ax_access(const char *action,const void *p,size_t n,const char *field,const char *fn){ if(!ax_active){return;}const char *domain;size_t offset; if(!locate(p,n,&domain,&offset))return; fprintf(ax_file,"{\"event\":\"%s\",\"domain\":\"%s\",\"offset\":%llu,\"field\":\"%s\",\"function\":\"%s\",",action,domain,(unsigned long long)offset,field,fn); blob("value",p,n);fputs("}\n",ax_file); } void ax_bind(NativePropertyCache *p,NativePipeCache *pipes){ax_cache=p;ax_pipes=pipes;} void ax_begin(unsigned long long jac,int group,int pos,double t,const double *inputs,int n){ ax_active=(pos==52 && (group==-1 || group==18)) || (pos==16 && (group==-1 || group==6)); if(!ax_active){return;} if(!ax_file){ax_file=fopen("access.jsonl","wb");if(!ax_file)abort();setvbuf(ax_file,NULL,_IOFBF,1024*1024);} ax_pending=1; fprintf(ax_file,"{\"event\":\"begin\",\"id\":%llu,\"jac\":%llu,\"group\":%d,\"position\":%d,\"t\":%.17g,\"stateSize\":%llu,\"pipeSize\":%llu,",++ax_id,jac,group,pos,t,(unsigned long long)sizeof(NativePropertyState),(unsigned long long)sizeof(NativePipeCache)); blob("inputs",inputs,n*sizeof(double));fputs("}\n",ax_file);snapshot("entry"); } void ax_end(const double *outputs,int n){if(!ax_active){return;}snapshot("exit");fputs("{\"event\":\"end\",\"completed\":true,",ax_file);blob("outputs",outputs,n*sizeof(double));fputs("}\n",ax_file);ax_active=0;} void ax_result(int result){if(ax_pending){fprintf(ax_file,"{\"event\":\"eval_return\",\"result\":%d}\n",result);ax_pending=0;}} void ax_finish(void){if(ax_file){fclose(ax_file);ax_file=NULL;}} void ax_query(const char *kind,const NativeMedium *m,double p,double second){ if(!ax_active){return;}double key[]={p,second,m->R,m->cp,m->Tref,m->slope,m->mu,m->muT,m->S}; fprintf(ax_file,"{\"event\":\"query\",\"kind\":\"%s\",\"mediumKind\":%d,\"count\":%llu,",kind,m->real_helium,(unsigned long long)ax_cache->count); blob("key",key,sizeof(key));fputs("}\n",ax_file); } void ax_match(const char *kind,NativePropertyState *s){if(!ax_active){return;}fprintf(ax_file,"{\"event\":\"match\",\"kind\":\"%s\",\"hit\":%s,\"slot\":%lld}\n",kind,s?"true":"false",s?(long long)(s-ax_cache->states):-1LL);} void ax_new(NativePropertyCache *cache,NativePropertyState *s,int valid){ if(!ax_active){return;}const char *domain;size_t offset;int stored=locate(s,sizeof(*s),&domain,&offset) && !strcmp(domain,"states"); fprintf(ax_file,"{\"event\":\"allocate\",\"validInput\":%s,\"slot\":%lld,\"countAfter\":%llu,\"capacity\":%llu,\"branch\":\"%s\"}\n",valid?"true":"false",stored?(long long)(offset/sizeof(*s)):-1LL,(unsigned long long)(cache?cache->count:0),(unsigned long long)(cache?cache->capacity:0),stored?"append":"scratch"); } unsigned ax_test(NativePropertyState *s,unsigned mask,const char *fn){ unsigned value=s->valid&mask; if(ax_active){ const char *domain;size_t offset; int stored=locate(s,sizeof(*s),&domain,&offset) && !strcmp(domain,"states"); fprintf(ax_file,"{\"event\":\"valid_test\",\"slot\":%lld,\"mask\":%u,\"value\":%u,\"function\":\"%s\"}\n",stored?(long long)(offset/sizeof(*s)):-1LL,mask,value,fn); } return value; } void ax_scalar(const char *action,NativeJacobianScalars *cache,int kind,int medium,const double *inputs,size_t n,int hit,const double *value){ if(!ax_active){return;}fprintf(ax_file,"{\"event\":\"scalar_%s\",\"kind\":%d,\"mediumKind\":%d,\"hit\":%d,\"recording\":%d,\"capacity\":%llu,",action,kind,medium,hit,cache?cache->recording:-1,(unsigned long long)(cache?cache->capacity:0)); blob("key",inputs,n*sizeof(double));if(value){fputc(',',ax_file);blob("value",value,sizeof(double));}fputs("}\n",ax_file); }