/* Included after the unchanged local_probe_support.c, so baseline snapshots are observed directly. None of the original guard or restore code is edited. */ #include "context_fallback_diag.h" #include /* DIAG_TABLES */ int dx_mode,dx_selected,dx_region=-1,dx_position=-1,dx_shadow; static uint64_t dx_jac,dx_sampled,dx_tick0,dx_q0,dx_region_tick,dx_op_tick; static unsigned dx_stride=16,dx_seed=1,dx_pick; static double dx_time; typedef struct { uint64_t attempts,compares,failures,region_ticks,op_ticks,ops; uint64_t input_diff_ops,output_diff_ops,exit_output_diff,exit_context_diff; } DxRegion; static DxRegion dx_stats[LP_NC][LP_NR]; static uint64_t dx_op_count[LP_NC][LP_NO],dx_op_ticks[LP_NC][LP_NO]; static uint64_t dx_kernel_count[LP_NR][DX_NK],dx_kernel_inclusive[LP_NR][DX_NK],dx_kernel_exclusive[LP_NR][DX_NK]; static double dx_inputs[DX_NIN],dx_outputs[DX_NOUT]; static FILE *dx_fail_file,*dx_matrix_file; static FILE *dx_input_file; static FILE *dx_create_file; static int dx_trace,dx_details,dx_first_context=-999,dx_seen[LP_NB],dx_source[LP_NB]; static Snapshot dx_history[LP_NB]; static struct {uint64_t start,child;int kind,region;} dx_stack[64]; static int dx_depth; typedef struct {const char *name;size_t offset,size;int floating;} DxField; #define DX_FIELD(type,field,float_flag) {#field,offsetof(type,field),sizeof(((type*)0)->field),float_flag} #define DX_MEDIUM(type,field,float_flag) {"medium." #field,offsetof(type,medium)+offsetof(NativeMedium,field),sizeof(((NativeMedium*)0)->field),float_flag} #define DX_MEDIUM_FIELDS(type) DX_MEDIUM(type,real_helium,0),DX_MEDIUM(type,R,1),DX_MEDIUM(type,cp,1),DX_MEDIUM(type,Tref,1),DX_MEDIUM(type,slope,1),DX_MEDIUM(type,mu,1),DX_MEDIUM(type,muT,1),DX_MEDIUM(type,S,1) static const DxField dx_state_fields[]={DX_MEDIUM_FIELDS(NativePropertyState), DX_FIELD(NativePropertyState,p,1),DX_FIELD(NativePropertyState,T,1),DX_FIELD(NativePropertyState,h,1), DX_FIELD(NativePropertyState,rho,1),DX_FIELD(NativePropertyState,mu,1),DX_FIELD(NativePropertyState,isentropic_factor,1), DX_FIELD(NativePropertyState,isentropic_exponent,1),DX_FIELD(NativePropertyState,valid,0), DX_FIELD(NativePropertyState,temperatures,0),DX_FIELD(NativePropertyState,jacobian,0)}; static const DxField dx_pipe_fields[]={DX_MEDIUM_FIELDS(NativePipeCache), DX_FIELD(NativePipeCache,p1,1),DX_FIELD(NativePipeCache,p2,1),DX_FIELD(NativePipeCache,T,1), DX_FIELD(NativePipeCache,diameter,1),DX_FIELD(NativePipeCache,length,1),DX_FIELD(NativePipeCache,roughness,1), DX_FIELD(NativePipeCache,flow,1),DX_FIELD(NativePipeCache,kind,0),DX_FIELD(NativePipeCache,valid,0)}; typedef struct {int kind,index,field;size_t offset,size;uint64_t baseline,trial;} DxDifference; static DxDifference dx_difference(NativePropertyCache*,NativePipeCache*,Snapshot*); static void dx_boundary(int pos,int source,NativePropertyCache *p,NativePipeCache *pipes){ if(!dx_trace || lp_color<0)return; int v=dx_version[pos];if(dx_seen[v])return; Snapshot *s=&dx_history[v];memset(s,0,sizeof(*s)); s->count=p->count;s->capacity=p->capacity;s->temperatures=p->temperatures;s->jacobian=p->jacobian; memcpy(s->states,p->states,p->count*sizeof(*p->states));memcpy(s->pipes,pipes,sizeof(s->pipes)); dx_seen[v]=1;dx_source[v]=source; if(dx_first_context==-999 && dx_difference(p,pipes,&saved->snapshots[v]).kind)dx_first_context=source; } static int dx_field_equal(Snapshot *a,Snapshot *b,DxDifference d){ if(d.kind==1){uint64_t x[]={a->count,a->capacity,(uintptr_t)a->temperatures,(uintptr_t)a->jacobian};uint64_t y[]={b->count,b->capacity,(uintptr_t)b->temperatures,(uintptr_t)b->jacobian};return x[d.field]==y[d.field];} if(d.kind==2 && ((size_t)d.index>=a->count || (size_t)d.index>=b->count))return (size_t)d.index>=a->count && (size_t)d.index>=b->count; unsigned char *x=(unsigned char*)(d.kind==2?(void*)&a->states[d.index]:(void*)&a->pipes[d.index]); unsigned char *y=(unsigned char*)(d.kind==2?(void*)&b->states[d.index]:(void*)&b->pipes[d.index]); return memcmp(x+d.offset,y+d.offset,d.size)==0; } static int dx_origin(DxDifference d,int v,int *first){ int previous_equal=1,origin=-999;*first=-999; for(int i=0;i<=v;i++)if(dx_seen[i]){ int equal=dx_field_equal(&dx_history[i],&saved->snapshots[i],d); if(!equal && previous_equal){origin=dx_source[i];if(*first==-999)*first=origin;} previous_equal=equal; } return origin; } static DxDifference dx_difference(NativePropertyCache *p,NativePipeCache *pipes,Snapshot *b){ DxDifference d={0,-1,-1,0,0,0,0}; uint64_t bm[]={b->count,b->capacity,(uintptr_t)b->temperatures,(uintptr_t)b->jacobian}; uint64_t pm[]={p->count,p->capacity,(uintptr_t)p->temperatures,(uintptr_t)p->jacobian}; for(int i=0;i<4;i++)if(bm[i]!=pm[i]){d.kind=1;d.field=i;d.baseline=bm[i];d.trial=pm[i];return d;} for(int kind=2;kind<=3;kind++){ size_t size=kind==2?sizeof(NativePropertyState):sizeof(NativePipeCache),count=kind==2?b->count:LP_NPC; const unsigned char *a=(const unsigned char*)(kind==2?(void*)b->states:(void*)b->pipes),*c=(const unsigned char*)(kind==2?(void*)p->states:(void*)pipes); const DxField *fields=kind==2?dx_state_fields:dx_pipe_fields; int nf=kind==2?(int)(sizeof(dx_state_fields)/sizeof(*dx_state_fields)):(int)(sizeof(dx_pipe_fields)/sizeof(*dx_pipe_fields)); for(size_t i=0;i=fields[f].offset && offsnapshots[lp_before[r]]); if(!d.kind){fprintf(stderr,"failure without difference\n");abort();} int first=-999,origin=dx_trace?dx_origin(d,dx_version[dx_start_pos[r]],&first):-999; fprintf(dx_fail_file,"{\"jac\":%llu,\"t\":%.17g,\"group\":%d,\"region\":%d,\"kind\":%d,\"index\":%d,\"field\":%d,\"offset\":%llu,\"baseline\":\"%016llx\",\"trial\":\"%016llx\",\"firstOrigin\":%d,\"persistentOrigin\":%d,\"firstContextOrigin\":%d}\n", (unsigned long long)(dx_jac-1),dx_time,lp_color,r,d.kind,d.index,d.field,(unsigned long long)d.offset,(unsigned long long)d.baseline,(unsigned long long)d.trial,first,origin,dx_first_context); } void dx_initialize(void){ const char *m=getenv("CONTEXT_DIAG_MODE"),*s=getenv("CONTEXT_DIAG_STRIDE"),*seed=getenv("CONTEXT_DIAG_SEED"),*mat=getenv("CONTEXT_DIAG_MATRICES"); dx_mode=m?atoi(m):1;dx_stride=s?(unsigned)atoi(s):16;dx_seed=seed?(unsigned)atoi(seed):1; dx_q0=lp_tick();dx_tick0=dx_clock(); if(dx_mode==1 || dx_mode==5){dx_fail_file=fopen("failures.jsonl","wb");if(!dx_fail_file)abort();setvbuf(dx_fail_file,NULL,_IOFBF,1024*1024);} if(dx_mode==5){dx_input_file=fopen("trace-inputs.jsonl","wb");if(!dx_input_file)abort();} if(dx_mode==5){dx_create_file=fopen("trace-created.jsonl","wb");if(!dx_create_file)abort();} if(mat && atoi(mat)){dx_matrix_file=fopen("jacobians.bin","wb");if(!dx_matrix_file)abort();setvbuf(dx_matrix_file,NULL,_IOFBF,1024*1024);} } void dx_jacobian(void){ unsigned pos=(unsigned)(dx_jac++%(dx_stride?dx_stride:1)); if(!pos){dx_seed^=dx_seed<<13;dx_seed^=dx_seed>>17;dx_seed^=dx_seed<<5;dx_pick=dx_seed%(dx_stride?dx_stride:1);} dx_selected=dx_mode==1 || dx_mode==5 || (dx_stride && pos==dx_pick); dx_trace=dx_mode==5; dx_details=dx_mode==5 && (dx_jac==1 || dx_jac==201 || dx_jac==451 || dx_jac==701 || dx_jac==896); if(dx_selected)dx_sampled++; } void dx_eval_begin(double t,const double *y){(void)y;dx_time=t;dx_region=-1;dx_position=-1;dx_first_context=-999;memset(dx_seen,0,sizeof(dx_seen));} void dx_eval_end(void){if(dx_region>=0){fprintf(stderr,"unclosed fallback region\n");abort();}dx_position=-1;} void dx_schedule(NativePropertyCache *p,NativePipeCache *pipes){dx_region=-1;dx_boundary(0,-2,p,pipes);} int dx_reuse(int r,NativePropertyCache *p,NativePipeCache *pipes,double *pv,double *h,double *q,double *w,double *fb){ int ok=lp_reuse(r,p,pipes,pv,h,q,w,fb); DxRegion *s=&dx_stats[lp_color][r];s->attempts++;if(dx_contextual[r])s->compares++; if(!ok){ if(!dx_contextual[r])abort(); s->failures++;dx_region=r; if(dx_fail_file)dx_failure(r,p,pipes); if(dx_mode>=2 && dx_mode<=4)dx_region_tick=dx_clock(); } else dx_boundary(lp_end[r],-1000-r,p,pipes); return ok; } void dx_op_begin(int pos,const double *inputs){ dx_position=pos; if(lp_color<0){if(dx_mode==1 || dx_mode==5)memcpy(dx_inputs+dx_in_offset[pos],inputs,(dx_in_offset[pos+1]-dx_in_offset[pos])*sizeof(double));return;} if(dx_details){ int any=0; for(int i=0;i=2 && dx_mode<=4)dx_stats[lp_color][r].region_ticks+=dx_clock()-dx_region_tick; if(dx_mode==1 || dx_mode==5){ double *dst[]={p,h,q,w,fb};double *src[]={saved->p,saved->h,saved->q,saved->w,saved->fb};int changed=0; for(int i=lp_first_output[r];isnapshots[lp_after[r]]).kind!=0; } dx_region=-1; } uint64_t dx_kernel_begin(int kind){ if(dx_mode==5 && dx_details && !dx_shadow && dx_position>=0){ if(dx_region>=0 && lp_color>=0)dx_kernel_count[dx_region][kind]++; if(dx_depth>=64)abort(); dx_stack[dx_depth].kind=kind;dx_depth++;return 1; } if(!dx_selected || dx_shadow || dx_region<0 || lp_color<0)return 0; dx_kernel_count[dx_region][kind]++; if(dx_mode!=4)return 0; if(dx_depth>=64)abort(); uint64_t t=dx_clock();dx_stack[dx_depth].start=t;dx_stack[dx_depth].child=0;dx_stack[dx_depth].kind=kind;dx_stack[dx_depth].region=dx_region;dx_depth++;return t; } void dx_kernel_end(int kind,uint64_t start){ if(!start)return; if(start==1 && dx_mode==5){if(--dx_depth<0 || dx_stack[dx_depth].kind!=kind)abort();return;} uint64_t elapsed=dx_clock()-start;int i=--dx_depth; if(i<0 || dx_stack[i].kind!=kind)abort(); int r=dx_stack[i].region;dx_kernel_inclusive[r][kind]+=elapsed;dx_kernel_exclusive[r][kind]+=elapsed-dx_stack[i].child; if(i)dx_stack[i-1].child+=elapsed; } void dx_property_created(NativePropertyCache *p,NativePropertyState *s){ if(!dx_details || dx_position<0 || !p)return; uintptr_t a=(uintptr_t)s,b=(uintptr_t)p->states; int slot=a>=b && acapacity*sizeof(*s)?(int)((a-b)/sizeof(*s)):-1; fprintf(dx_create_file,"{\"jac\":%llu,\"group\":%d,\"position\":%d,\"slot\":%d,\"p\":%.17g,\"T\":%.17g,\"count\":%llu,\"path\":[",(unsigned long long)(dx_jac-1),lp_color,dx_position,slot,s->p,s->T,(unsigned long long)p->count); for(int i=0;iattempts)continue; fprintf(f,"%s{\"group\":%d,\"region\":%d,\"attempts\":%llu,\"compares\":%llu,\"failures\":%llu,\"regionTicks\":%llu,\"opTicks\":%llu,\"ops\":%llu,\"inputDiffOps\":%llu,\"outputDiffOps\":%llu,\"exitOutputDiff\":%llu,\"exitContextDiff\":%llu}",comma++?",":"",g,r,(unsigned long long)s->attempts,(unsigned long long)s->compares,(unsigned long long)s->failures,(unsigned long long)s->region_ticks,(unsigned long long)s->op_ticks,(unsigned long long)s->ops,(unsigned long long)s->input_diff_ops,(unsigned long long)s->output_diff_ops,(unsigned long long)s->exit_output_diff,(unsigned long long)s->exit_context_diff); } fprintf(f,"],\"operations\":[");comma=0; for(int g=0;g