216216import com .oracle .graal .python .nodes .object .GetClassNode .GetPythonObjectClassNode ;
217217import com .oracle .graal .python .nodes .object .IsNode ;
218218import com .oracle .graal .python .nodes .util .ExceptionStateNodes ;
219- import com .oracle .graal .python .runtime .ExecutionContext .BoundaryCallContext ;
220219import com .oracle .graal .python .runtime .ExecutionContext .CalleeContext ;
221220import com .oracle .graal .python .runtime .IndirectCallData .BoundaryCallData ;
222221import com .oracle .graal .python .runtime .PythonContext ;
284283import com .oracle .truffle .api .frame .MaterializedFrame ;
285284import com .oracle .truffle .api .frame .VirtualFrame ;
286285import com .oracle .truffle .api .library .CachedLibrary ;
287- import com .oracle .truffle .api .nodes .EncapsulatingNodeReference ;
288286import com .oracle .truffle .api .nodes .ExplodeLoop ;
289287import com .oracle .truffle .api .nodes .Node ;
290288import com .oracle .truffle .api .nodes .UnexpectedResultException ;
@@ -362,9 +360,16 @@ public abstract class PBytecodeDSLRootNode extends PRootNode implements Bytecode
362360
363361 @ Child private transient CalleeContext calleeContext = CalleeContext .create ();
364362 @ Child private transient ExceptionStateNodes .GetCaughtExceptionNode getCaughtExceptionNode ;
365- @ Child private transient MaterializeFrameNode traceMaterializeFrameNode = null ;
366363 @ Child private transient ChainExceptionsNode chainExceptionsNode ;
367- @ Child private transient BoundaryCallData tracingAndProfilingBoundaryCallData ;
364+
365+ private static final class TracingNodes extends Node {
366+ @ Child MaterializeFrameNode materializeFrameNode = MaterializeFrameNode .create ();
367+ @ Child CallNode tracingCallNode = CallNode .create ();
368+ @ Child CallNode profilingCallNode = CallNode .create ();
369+ }
370+
371+ // Not a child of this root, adopted by the BytecodeNode
372+ private transient TracingNodes tracingNodes ;
368373
369374 // These fields are effectively final, but can only be set after construction.
370375 @ CompilationFinal protected transient BytecodeDSLCodeUnit co ;
@@ -532,12 +537,20 @@ public final void ensureTraceAndProfileEnabled() {
532537 getRootNodes ().update (TRACE_AND_PROFILE_CONFIG );
533538 }
534539
535- private PFrame ensurePyFrame (VirtualFrame frame , BytecodeNode location ) {
536- if (traceMaterializeFrameNode == null ) {
540+ private TracingNodes getTracingNodes (BytecodeNode location ) {
541+ /*
542+ * The TracingNodes node must be child of the BytecodeNode and not the PBytecodeRootNode, so
543+ * in case BytecodeNode changed, we must reinsert it
544+ */
545+ if (tracingNodes == null || tracingNodes .getParent () != location ) {
537546 CompilerDirectives .transferToInterpreterAndInvalidate ();
538- traceMaterializeFrameNode = insert (MaterializeFrameNode . create ());
547+ tracingNodes = location . insert (new TracingNodes ());
539548 }
540- return traceMaterializeFrameNode .executeOnStack (frame , location , true , true );
549+ return tracingNodes ;
550+ }
551+
552+ private PFrame ensurePyFrame (VirtualFrame frame , BytecodeNode location ) {
553+ return getTracingNodes (location ).materializeFrameNode .executeOnStack (frame , location , true , false );
541554 }
542555
543556 private void syncLocalsBackToFrame (VirtualFrame frame , PFrame pyFrame , BytecodeNode location ) {
@@ -546,31 +559,6 @@ private void syncLocalsBackToFrame(VirtualFrame frame, PFrame pyFrame, BytecodeN
546559 }
547560 }
548561
549- /**
550- * When tracing/profiling is enabled, we emit a lot of extra operations. Reduce compiled code
551- * size by putting the calls behind a boundary (the uncached invoke will eventually perform an
552- * indirect call anyway).
553- */
554- @ TruffleBoundary
555- private static Object doInvokeProfileOrTraceFunctionBoundary (Object fun , PFrame pyFrame , TruffleString eventName , Object arg ) {
556- return CallTernaryMethodNode .getUncached ().execute (null , fun , pyFrame , eventName , arg == null ? PNone .NONE : arg );
557- }
558-
559- private Object doInvokeProfileOrTraceFunction (VirtualFrame frame , BytecodeNode location , PythonThreadState threadState , Object fun , PFrame pyFrame , TruffleString eventName , Object arg ) {
560- if (tracingAndProfilingBoundaryCallData == null || tracingAndProfilingBoundaryCallData .getParent () != location ) {
561- // The IndirectCallData node must be child of the BytecodeNode and not the
562- // PBytecodeRootNode, so in case BytecodeNode changed, we must reinsert it
563- CompilerDirectives .transferToInterpreterAndInvalidate ();
564- tracingAndProfilingBoundaryCallData = location .insert (BoundaryCallData .createFor (this ));
565- }
566- Object saved = BoundaryCallContext .enter (frame , threadState , tracingAndProfilingBoundaryCallData );
567- try {
568- return doInvokeProfileOrTraceFunctionBoundary (fun , pyFrame , eventName , arg );
569- } finally {
570- BoundaryCallContext .exit (frame , threadState , saved );
571- }
572- }
573-
574562 @ InliningCutoff
575563 private void invokeProfileFunction (VirtualFrame virtualFrame , BytecodeNode location , Object profileFun ,
576564 PythonContext .PythonThreadState threadState , PythonContext .ProfileEvent event , Object arg ) {
@@ -579,13 +567,9 @@ private void invokeProfileFunction(VirtualFrame virtualFrame, BytecodeNode locat
579567 }
580568 threadState .profilingStart ();
581569 PFrame pyFrame = ensurePyFrame (virtualFrame , location );
582- EncapsulatingNodeReference encapsulating = EncapsulatingNodeReference .getCurrent ();
583- Node oldEncapsulatingNode = encapsulating .set (location );
584570 try {
585- // Force locals dict sync, so that we can sync them back later
586- GetFrameLocalsNode .executeUncached (pyFrame , false );
587571 pyFrame .setLocalsAccessed (false );
588- Object result = doInvokeProfileOrTraceFunction ( virtualFrame , location , threadState , profileFun , pyFrame , event .name , arg );
572+ Object result = getTracingNodes ( location ). profilingCallNode . execute ( virtualFrame , profileFun , pyFrame , event .name , arg == null ? PNone . NONE : arg );
589573 syncLocalsBackToFrame (virtualFrame , pyFrame , location );
590574 Object realResult = result == PNone .NONE ? null : result ;
591575 pyFrame .setLocalTraceFun (realResult );
@@ -594,7 +578,6 @@ private void invokeProfileFunction(VirtualFrame virtualFrame, BytecodeNode locat
594578 throw e ;
595579 } finally {
596580 threadState .profilingStop ();
597- encapsulating .set (oldEncapsulatingNode );
598581 }
599582 }
600583
@@ -619,8 +602,6 @@ private void invokeTraceFunction(VirtualFrame virtualFrame, BytecodeNode locatio
619602 }
620603 Object nonNullArg = arg == null ? PNone .NONE : arg ;
621604
622- EncapsulatingNodeReference encapsulating = EncapsulatingNodeReference .getCurrent ();
623- Node oldEncapsulatingNode = encapsulating .set (location );
624605 try {
625606 /**
626607 * The PFrame syncs to the line of the current bci. Sometimes this location is
@@ -631,10 +612,8 @@ private void invokeTraceFunction(VirtualFrame virtualFrame, BytecodeNode locatio
631612 pyFrame .setLineLock (line );
632613 }
633614
634- // Force locals dict sync, so that we can sync them back later
635- GetFrameLocalsNode .executeUncached (pyFrame , true );
636615 pyFrame .setLocalsAccessed (false );
637- Object result = doInvokeProfileOrTraceFunction ( virtualFrame , location , threadState , traceFn , pyFrame , event .pythonName , nonNullArg );
616+ Object result = getTracingNodes ( location ). tracingCallNode . execute ( virtualFrame , traceFn , pyFrame , event .pythonName , nonNullArg );
638617 syncLocalsBackToFrame (virtualFrame , pyFrame , location );
639618 // https://github.com/python/cpython/issues/104232
640619 if (useLocalFn ) {
@@ -653,7 +632,6 @@ private void invokeTraceFunction(VirtualFrame virtualFrame, BytecodeNode locatio
653632 pyFrame .lineUnlock ();
654633 }
655634 threadState .tracingStop ();
656- encapsulating .set (oldEncapsulatingNode );
657635 }
658636 }
659637
0 commit comments