php方案 Side Exits: 解释 JIT 在类型推断失败时,是如何从生成好的机器码回退(De-optimize)到解释器的。

php方案 Side Exits: 解释 JIT 在类型推断失败时,是如何从生成好的机器码回退(De-optimize)到解释器的。 JIT Side Exits 反优化大白话JIT编译函数时会赌一把“我猜这个变量一直是int”→ 按int生成机器码结果某次传进来个stringJIT赌输了立刻踩刹车把控制权交还给解释器这个踩刹车的出口就叫Side Exit代码复现?php// JIT看前1000次调用都是int生成了int专用机器码functionadd($a,$b){return$a$b;}// 前面正常JIT优化生效for($i0;$i1000;$i)add(1,2);// 突然传string类型推断失败触发Side Exitadd(hello,world);// JIT我不行了解释器你来用vld看实际发生了什么peclinstallvldphp-dopcache.enable_cli1\-dopcache.jit1255\-dopcache.jit_buffer_size64M\-dvld.active1\-dvld.execute0\test.php21# 看到这个就是Side Exit埋的检查点 GUARD_TYPE $a IS_LONG → 类型不对就跳出机器码 GUARD_TYPE $b IS_LONG → 回退到解释器回退全过程正常路径快 机器码: mov eax, [a] add eax, [b] ← 直接CPU指令飞快 类型不对时Side Exit 机器码: cmp type, IS_LONG jne side_exit ← 跳到出口 ↓ 恢复zval状态把寄存器里的值写回PHP变量 ↓ 跳回解释器的opcode handler ↓ 按普通方式执行慢但正确验证Side Exit次数?php$statusopcache_get_status();// 看JIT缓冲区消耗// Side Exit频繁会导致buffer_free不断减少echo$status[jit][buffer_free].\n;// Side Exit太多JIT会直接放弃这个函数// 不再编译它标记为 too polymorphic结论类型稳定 → JIT一路畅通机器码跑到底 类型突变 → 踩Side Exit溜回解释器 反复突变 → JIT直接放弃这个函数不编译了想让JIT发挥最大效果函数里的变量类型别乱变。