@@ -121,23 +121,25 @@ static int irseq_of(const kvlangParam_t *p) {
121121}
122122
123123/* 函数内跳转:只改 PC 的 [irseq],帧不变。目标非法 → RuntimeError,返回 -1。 */
124- static int jump_to (kvlangKv_t * kv , const char * vtid , const char * pc ,
125- const kvlangParam_t * target , const char * op ) {
124+ static int jump_to (kvlangFrame_t * f , const kvlangParam_t * target , const char * op ) {
126125 int irseq = irseq_of (target );
127126 if (irseq < 0 ) {
128127 char msg [256 ];
129128 snprintf (msg , sizeof msg ,
130129 "RuntimeError: %s target is not an int64 irseq: %s (kind=%s)" ,
131130 op , target -> name ? target -> name : "" ,
132131 kvlangXvalueKind (& target -> val ));
133- kvlangVthreadSetError (kv , vtid , pc , msg );
132+ kvlangVthreadSetError (f -> kv , f -> vtid , f -> pc , msg );
134133 return -1 ;
135134 }
136- char * fr = kvlangKeytreeFrameRoot (pc );
135+ /* 帧根优先用主循环缓存的(br/goto 帧不变,借它免每次 malloc)。 */
136+ char * owned = NULL ;
137+ const char * fr = f -> frame_root ;
138+ if (!fr ) { owned = kvlangKeytreeFrameRoot (f -> pc ); fr = owned ; }
137139 char * np = kvlangKeytreeIrseqPc (fr , irseq );
138- free (fr );
139- kvlangVthreadSet ( kv , vtid , np , "running" );
140- kvlangLogDebug ("[%s] %s → %s" , vtid , op , np );
140+ free (owned );
141+ kvlangVthreadAdvance ( f , np , "running" );
142+ kvlangLogDebug ("[%s] %s → %s" , f -> vtid , op , np );
141143 free (np );
142144 return 0 ;
143145}
@@ -789,7 +791,7 @@ int kvlangCtlCall(kvlangFrame_t *f) {
789791 char * sub = handle_call (f -> kv , f -> pc , f -> inst );
790792 if (!sub )
791793 return -1 ;
792- kvlangVthreadSet ( f -> kv , f -> vtid , sub , "running" );
794+ kvlangVthreadAdvance ( f , sub , "running" );
793795 free (sub );
794796 return 0 ;
795797}
@@ -802,7 +804,7 @@ int kvlangCtlReturn(kvlangFrame_t *f) {
802804 kvlangVthreadSetDone (f -> kv , f -> vtid , "ok" );
803805 return 0 ;
804806 }
805- kvlangVthreadSet ( f -> kv , f -> vtid , parent , "running" );
807+ kvlangVthreadAdvance ( f , parent , "running" );
806808 free (parent );
807809 return 0 ;
808810}
@@ -816,7 +818,7 @@ int kvlangCtlGoto(kvlangFrame_t *f) {
816818 kvlangVthreadSetError (f -> kv , f -> vtid , f -> pc , msg );
817819 return -1 ;
818820 }
819- return jump_to (f -> kv , f -> vtid , f -> pc , & inst -> reads [0 ], OP_GOTO );
821+ return jump_to (f , & inst -> reads [0 ], OP_GOTO );
820822}
821823
822824int kvlangCtlBr (kvlangFrame_t * f ) {
@@ -852,7 +854,7 @@ int kvlangCtlBr(kvlangFrame_t *f) {
852854 }
853855 bool taken = kvlangScalarI64 (kvlangXvalueScalar (& cond )) != 0 ;
854856 kvlangXvalueFree (& cond );
855- return jump_to (f -> kv , f -> vtid , f -> pc , & inst -> reads [taken ? 1 : 2 ], OP_BR );
857+ return jump_to (f , & inst -> reads [taken ? 1 : 2 ], OP_BR );
856858}
857859
858860/* 动态调用:以运行时得到的 funckey 在当前 vthread 造一次 OP_CALL(不新开 vid),
@@ -1027,28 +1029,40 @@ int kvlangKvcpuExecuteMode(kvlangKv_t *kv, const char *pc, kvmode_t mode,
10271029 char * cur = strdup (pc );
10281030 char * cur_frame = NULL ,
10291031 * cur_funcdir = NULL ; /* 帧不变时 funcdir 只读一次,供缓存键 */
1032+ int cur_depth = 0 ; /* 帧深度,随 cur_frame 一起缓存 */
10301033 int rc = 0 ;
1031- /* status 跨轮携带:尾部 VthreadGet 已连 pc 一并取出,下轮直接复用,省掉背靠背重读
1032- * (vthread 记录在两次 get 之间不被改写;status 串由 ValueString 自持,跨 ReadReset 存活) 。 */
1034+ /* status:每步从 kvspace 回读的**源值**,不当缓存用(下轮开头即重读)。
1035+ * 同时借给本步的 kvlangFrame_t.status_known,供 Advance 判断是否真要写 status 。 */
10331036 char * status = NULL ;
1034- {
1035- char * pcv = NULL ;
1036- kvlangVthreadGet (kv , vtid , & pcv , & status );
1037- free (pcv );
1038- }
10391037 for (;;) {
10401038 /* 指令边界:回收上条指令执行期借出的读池(cache 指令的读参已 Materialize 自持,不受影响)。
10411039 * durable 惰性写不再清池,全靠此处回收;shm 常驻映射侧为 no-op。 */
10421040 kvlangKvReadReset (kv );
1041+ /* 状态门(spec [[执行模型]] 步骤 1):每指令边界从 kvspace 回读 ‥status,只读 1 个 key
1042+ * (走 vtid key 缓存)。不得改用进程内副本——那是状态的第二份事实源:外部把 ‥status
1043+ * 置 paused/error(暂停、接管、终止)必须在下一步就被看见,且 kvspace 始终等于真实状态。 */
1044+ free (status );
1045+ status = NULL ;
1046+ kvlangVthreadStatusGet (kv , vtid , & status );
10431047 if (!status ||
10441048 (strcmp (status , "init" ) != 0 && strcmp (status , "running" ) != 0 &&
10451049 strcmp (status , "wait" ) != 0 )) {
10461050 break ;
10471051 }
1048- free (status );
1049- status = NULL ;
10501052
1051- int depth = kvlangKeytreeFrameNum (cur );
1053+ /* 帧变(call/return/goto 跨帧)才重算根/深度/funcdir;帧内每步只比较前缀,免分配。 */
1054+ size_t frlen = kvlangKeytreeFrameRootLen (cur );
1055+ if (!cur_frame || strlen (cur_frame ) != frlen ||
1056+ strncmp (cur_frame , cur , frlen ) != 0 ) {
1057+ free (cur_frame );
1058+ cur_frame = malloc (frlen + 1 );
1059+ memcpy (cur_frame , cur , frlen );
1060+ cur_frame [frlen ] = 0 ;
1061+ free (cur_funcdir );
1062+ cur_funcdir = read_seglib (kv , cur_frame );
1063+ cur_depth = kvlangKeytreeFrameNum (cur );
1064+ }
1065+ int depth = cur_depth ;
10521066 if (depth > MAX_STACK_DEPTH ) {
10531067 char msg [256 ];
10541068 snprintf (msg , sizeof msg ,
@@ -1059,13 +1073,7 @@ int kvlangKvcpuExecuteMode(kvlangKv_t *kv, const char *pc, kvmode_t mode,
10591073 break ;
10601074 }
10611075
1062- char * fr = kvlangKeytreeFrameRoot (cur );
1063- if (!cur_frame || strcmp (cur_frame , fr ) != 0 ) {
1064- free (cur_frame );
1065- cur_frame = strdup (fr );
1066- free (cur_funcdir );
1067- cur_funcdir = read_seglib (kv , fr );
1068- }
1076+ const char * fr = cur_frame ; /* 借用(随 cur_frame 缓存同步),循环内无需 free */
10691077 const char * lastc = NULL ;
10701078 for (const char * p = cur ; (p = strstr (p , "/[" )) != NULL ; p += 2 )
10711079 lastc = p ;
@@ -1086,7 +1094,6 @@ int kvlangKvcpuExecuteMode(kvlangKv_t *kv, const char *pc, kvmode_t mode,
10861094 snprintf (msg , sizeof msg , "decode: %s" , err );
10871095 kvlangVthreadSetError (kv , vtid , cur , msg );
10881096 free (link_base );
1089- free (fr );
10901097 rc = -1 ;
10911098 break ;
10921099 }
@@ -1114,7 +1121,6 @@ int kvlangKvcpuExecuteMode(kvlangKv_t *kv, const char *pc, kvmode_t mode,
11141121 snprintf (msg , sizeof msg , "RuntimeError: no instruction at %s" ,
11151122 cur );
11161123 kvlangVthreadSetError (kv , vtid , cur , msg );
1117- free (fr );
11181124 if (tmp_owned )
11191125 kvlangRwirInstFree (& tmp );
11201126 rc = -1 ;
@@ -1123,9 +1129,12 @@ int kvlangKvcpuExecuteMode(kvlangKv_t *kv, const char *pc, kvmode_t mode,
11231129
11241130 int exec_err = 0 ;
11251131 char * yield = NULL ;
1132+ char * fb_pc = NULL ; /* 本指令的 PC 回传槽(见 kvlangFrame_t),免写后回读 */
11261133 if (inst -> op_id >= 0 ) {
11271134 /* 单表派发:native 算子与 control/copy 同居 myrwircaps,op_id 直查一跳到底。 */
1128- kvlangFrame_t f = {kv , vtid , cur , inst , & yield };
1135+ kvlangFrame_t f = {kv , vtid , cur , inst , & yield , & fb_pc };
1136+ f .frame_root = cur_frame ; /* 复用循环缓存的帧根,免每步重算 */
1137+ f .status_known = status ; /* 本步开始前读到的 ‥status(源值,借用) */
11291138 exec_err = kvlangBuiltinNative (& f );
11301139 if (exec_err == 0 && yield ) {
11311140 /* native(vthread·run return 模式)冒泡一个子 vthread 的 rwir pc 给上层驱动。
@@ -1134,9 +1143,9 @@ int kvlangKvcpuExecuteMode(kvlangKv_t *kv, const char *pc, kvmode_t mode,
11341143 * out_pc = yield ;
11351144 else
11361145 free (yield );
1137- free (fr );
11381146 if (tmp_owned )
11391147 kvlangRwirInstFree (& tmp );
1148+ free (fb_pc );
11401149 free (cur );
11411150 free (cur_frame );
11421151 free (cur_funcdir );
@@ -1153,9 +1162,9 @@ int kvlangKvcpuExecuteMode(kvlangKv_t *kv, const char *pc, kvmode_t mode,
11531162 if (exec_err == 0 && mode == KVMODE_RETURN ) {
11541163 if (out_pc )
11551164 * out_pc = strdup (cur );
1156- free (fr );
11571165 if (tmp_owned )
11581166 kvlangRwirInstFree (& tmp );
1167+ free (fb_pc );
11591168 free (cur );
11601169 free (cur_frame );
11611170 free (cur_funcdir );
@@ -1181,24 +1190,31 @@ int kvlangKvcpuExecuteMode(kvlangKv_t *kv, const char *pc, kvmode_t mode,
11811190 }
11821191 ci .writes = inst -> writes ;
11831192 kvlangFrame_t cf = {kv , vtid , cur , & ci , NULL };
1193+ cf .status_known = status ;
11841194 exec_err = kvlangCtlCall (& cf );
11851195 free (ci .opcode );
11861196 free (ci .reads [0 ].name );
11871197 free (ci .reads );
11881198 }
11891199
11901200 if (exec_err != 0 ) {
1191- free (fr );
11921201 if (tmp_owned )
11931202 kvlangRwirInstFree (& tmp );
1203+ free (fb_pc );
11941204 rc = -1 ;
11951205 break ;
11961206 }
11971207
11981208 char * newpc = NULL ;
1199- kvlangVthreadGet (kv , vtid , & newpc ,
1200- & status ); /* status 连 pc 一并取出,供下轮直接复用 */
1201- free (fr );
1209+ if (fb_pc ) {
1210+ /* 本指令经帧回传了新 PC:直接用(它就是本指令刚写进 kvspace 的值)。
1211+ * status 不回传——下一轮状态门照旧从 kvspace 回读。 */
1212+ newpc = fb_pc ;
1213+ fb_pc = NULL ;
1214+ } else {
1215+ /* 无回传(ext rwir / 用户 call / done 等):从 kvspace 回读 PC。 */
1216+ kvlangVthreadPcGet (kv , vtid , & newpc );
1217+ }
12021218 if (tmp_owned )
12031219 kvlangRwirInstFree (& tmp );
12041220 if (!newpc || !newpc [0 ]) {
0 commit comments