@@ -615,6 +615,7 @@ public final class PBytecodeRootNode extends PRootNode implements BytecodeOSRNod
615615 private static final byte TRACE_PROFILE_LINE = 1 ;
616616 private static final byte TRACE_PROFILE_NEW_FRAME = 1 << 1 ;
617617 private static final byte TRACE_PROFILE_EXISTING_FRAME = 1 << 2 ;
618+ private static final byte TRACE_PROFILE_SYNC_LOCALS_BACK = 1 << 3 ;
618619 @ CompilationFinal (dimensions = 1 ) byte [] traceProfileData ;
619620
620621 @ CompilationFinal private Object osrMetadata ;
@@ -3254,7 +3255,7 @@ private void invokeTraceFunction(VirtualFrame virtualFrame, Object arg, PythonCo
32543255 pyFrame .setLineLock (line );
32553256 }
32563257 Object result = doInvokeTraceFunction (event , pyFrame , traceFn , nonNullArg );
3257- syncLocalsBackToFrame (virtualFrame , pyFrame );
3258+ syncLocalsBackToFrame (virtualFrame , pyFrame , bci );
32583259 // https://github.com/python/cpython/issues/104232
32593260 if (useLocalFn ) {
32603261 Object realResult = result == PNone .NONE ? traceFn : result ;
@@ -3279,15 +3280,19 @@ private void invokeTraceFunction(VirtualFrame virtualFrame, Object arg, PythonCo
32793280 private static Object doInvokeTraceFunction (PythonContext .TraceEvent event , PFrame pyFrame , Object traceFn , Object nonNullArg ) {
32803281 // Force locals dict sync, so that we can sync them back later
32813282 GetFrameLocalsNode .executeUncached (pyFrame );
3283+ pyFrame .setLocalsAccessed (false );
32823284 return CallTernaryMethodNode .getUncached ().execute (null , traceFn , pyFrame , event .pythonName , nonNullArg );
32833285 }
32843286
3285- private void syncLocalsBackToFrame (VirtualFrame virtualFrame , PFrame pyFrame ) {
3287+ private void syncLocalsBackToFrame (VirtualFrame virtualFrame , PFrame pyFrame , int bci ) {
32863288 Frame localFrame = virtualFrame ;
32873289 if (co .isGeneratorOrCoroutine ()) {
32883290 localFrame = PArguments .getGeneratorFrame (virtualFrame );
32893291 }
3290- GetFrameLocalsNode .syncLocalsBackToFrame (co , this , pyFrame , localFrame );
3292+ if (pyFrame .localsAccessed ()) {
3293+ enterTraceProfile (bci , TRACE_PROFILE_SYNC_LOCALS_BACK );
3294+ GetFrameLocalsNode .syncLocalsBackToFrame (co , this , pyFrame , localFrame );
3295+ }
32913296 }
32923297
32933298 private void profileCEvent (VirtualFrame virtualFrame , Object callable , PythonContext .ProfileEvent event , MutableLoopData mutableData , byte tracingOrProfilingEnabled , int bci ) {
@@ -3327,7 +3332,7 @@ private void invokeProfileFunction(VirtualFrame virtualFrame, Object arg, Python
33273332
33283333 try {
33293334 Object result = doInvokeProfileFunction (arg , event , pyFrame , profileFun );
3330- syncLocalsBackToFrame (virtualFrame , pyFrame );
3335+ syncLocalsBackToFrame (virtualFrame , pyFrame , bci );
33313336 Object realResult = result == PNone .NONE ? null : result ;
33323337 pyFrame .setLocalTraceFun (realResult );
33333338 } catch (Throwable e ) {
@@ -3342,6 +3347,7 @@ private void invokeProfileFunction(VirtualFrame virtualFrame, Object arg, Python
33423347 private static Object doInvokeProfileFunction (Object arg , PythonContext .ProfileEvent event , PFrame pyFrame , Object profileFun ) {
33433348 // Force locals dict sync, so that we can sync them back later
33443349 GetFrameLocalsNode .executeUncached (pyFrame );
3350+ pyFrame .setLocalsAccessed (false );
33453351 return CallTernaryMethodNode .getUncached ().execute (null , profileFun , pyFrame , event .name , arg == null ? PNone .NONE : arg );
33463352 }
33473353
0 commit comments