194
194
import com .oracle .truffle .api .CompilerDirectives .CompilationFinal ;
195
195
import com .oracle .truffle .api .CompilerDirectives .TruffleBoundary ;
196
196
import com .oracle .truffle .api .CompilerDirectives .ValueType ;
197
+ import com .oracle .truffle .api .HostCompilerDirectives ;
197
198
import com .oracle .truffle .api .HostCompilerDirectives .BytecodeInterpreterSwitch ;
198
199
import com .oracle .truffle .api .Truffle ;
199
200
import com .oracle .truffle .api .TruffleLanguage ;
@@ -496,9 +497,9 @@ public final class PBytecodeRootNode extends PRootNode implements BytecodeOSRNod
496
497
@ Child private CalleeContext calleeContext = CalleeContext .create ();
497
498
@ Child private PythonObjectFactory factory = PythonObjectFactory .create ();
498
499
@ Child private ExceptionStateNodes .GetCaughtExceptionNode getCaughtExceptionNode ;
499
- @ Child private GetExceptionTracebackNode traceGetExceptionTracebackNode = null ;
500
- @ Child private MaterializeFrameNode traceMaterializeFrameNode = null ;
501
- @ Child private CallTernaryMethodNode traceCallTernaryMethodNode = null ;
500
+ // private GetExceptionTracebackNode traceGetExceptionTracebackNode = null;
501
+ private MaterializeFrameNode traceMaterializeFrameNode = null ;
502
+ // private CallTernaryMethodNode traceCallTernaryMethodNode = null;
502
503
503
504
private final LoopConditionProfile exceptionChainProfile1 = LoopConditionProfile .createCountingProfile ();
504
505
private final LoopConditionProfile exceptionChainProfile2 = LoopConditionProfile .createCountingProfile ();
@@ -1011,6 +1012,14 @@ private InterpreterContinuation(int bci, int stackTop) {
1011
1012
1012
1013
@ ValueType
1013
1014
private static final class MutableLoopData {
1015
+ /*
1016
+ * data for tracing
1017
+ */
1018
+ int pastBci ;
1019
+ int pastLine ;
1020
+ int returnLine ;
1021
+ PFrame pyFrame ;
1022
+
1014
1023
int loopCount ;
1015
1024
/*
1016
1025
* This separate tracking of local exception is necessary to make exception state saving
@@ -1054,6 +1063,8 @@ private Object executeUncached(VirtualFrame virtualFrame, Frame localFrame, Byte
1054
1063
return bytecodeLoop (virtualFrame , localFrame , osrNode , initialBci , initialStackTop , false , false );
1055
1064
}
1056
1065
1066
+ @ CompilationFinal private PythonLanguage cachedLanguage = null ;
1067
+
1057
1068
@ ExplodeLoop (kind = ExplodeLoop .LoopExplosionKind .MERGE_EXPLODE )
1058
1069
@ SuppressWarnings ("fallthrough" )
1059
1070
@ BytecodeInterpreterSwitch
@@ -1062,14 +1073,16 @@ private Object bytecodeLoop(VirtualFrame virtualFrame, Frame localFrame, Bytecod
1062
1073
Object [] arguments = virtualFrame .getArguments ();
1063
1074
Object globals = PArguments .getGlobals (arguments );
1064
1075
Object locals = PArguments .getSpecialArgument (arguments );
1065
-
1066
- boolean isGeneratorOrCoroutine = co .isGeneratorOrCoroutine ();
1067
- if (inCompiledCode && !isGeneratorOrCoroutine ) {
1068
- unboxVariables (localFrame );
1076
+ final PythonLanguage language ;
1077
+ if (cachedLanguage == null ) {
1078
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
1079
+ language = cachedLanguage = PythonLanguage .get (this );
1080
+ } else {
1081
+ language = cachedLanguage ;
1069
1082
}
1070
-
1071
- final PythonContext context = PythonContext .get (this );
1072
- final PythonContext .PythonThreadState threadState = context .getThreadState (PythonLanguage . get ( this ) );
1083
+ final Assumption noTrace = language . noTracingAssumption ;
1084
+ final PythonContext pythonContext = PythonContext .get (this );
1085
+ final PythonContext .PythonThreadState threadState = pythonContext .getThreadState (language );
1073
1086
1074
1087
/*
1075
1088
* We use an object as a workaround for not being able to specify which local variables are
@@ -1078,6 +1091,7 @@ private Object bytecodeLoop(VirtualFrame virtualFrame, Frame localFrame, Bytecod
1078
1091
MutableLoopData mutableData = new MutableLoopData ();
1079
1092
int stackTop = initialStackTop ;
1080
1093
int bci = initialBci ;
1094
+ mutableData .pastLine = -1 ;
1081
1095
1082
1096
byte [] localBC = bytecode ;
1083
1097
Object [] localConsts = consts ;
@@ -1093,34 +1107,29 @@ private Object bytecodeLoop(VirtualFrame virtualFrame, Frame localFrame, Bytecod
1093
1107
CompilerAsserts .partialEvaluationConstant (bci );
1094
1108
CompilerAsserts .partialEvaluationConstant (stackTop );
1095
1109
1096
- PFrame pyFrame ;
1097
-
1098
- int pastLine = -1 ;
1099
- if (threadState .getTraceFun () != null && !threadState .isTracing ()) {
1100
- pyFrame = ensurePyFrame (virtualFrame , null );
1110
+ if (!noTrace .isValid () && threadState .getTraceFun () != null && !threadState .isTracing ()) {
1111
+ mutableData .pyFrame = ensurePyFrame (virtualFrame , null );
1101
1112
// if we are simply continuing to run an OSR loop after the replacememnt, tracing an
1102
1113
// extra CALL event would be incorrect
1103
1114
if (!fromOSR ) {
1104
- pyFrame .setLocalTraceFun (invokeTraceFunction (threadState .getTraceFun (), null , threadState , virtualFrame , pyFrame , PythonContext .TraceEvent .CALL ,
1105
- initialBci == 0 ? getFirstLineno () : (pastLine = bciToLine (initialBci ))));
1115
+ mutableData . pyFrame .setLocalTraceFun (invokeTraceFunction (threadState .getTraceFun (), null , threadState , virtualFrame , mutableData . pyFrame , PythonContext .TraceEvent .CALL ,
1116
+ initialBci == 0 ? getFirstLineno () : (mutableData . pastLine = bciToLine (initialBci ))));
1106
1117
}
1107
- } else {
1108
- pyFrame = null ;
1109
1118
}
1110
1119
1111
- int returnLine = pastLine ;
1112
- int pastBci = initialBci ;
1120
+ mutableData . returnLine = mutableData . pastLine ;
1121
+ mutableData . pastBci = initialBci ;
1113
1122
1114
1123
int oparg = 0 ;
1115
1124
while (true ) {
1116
1125
final byte bc = localBC [bci ];
1117
1126
final int beginBci = bci ;
1118
- if (threadState .getTraceFun () != null && !threadState .isTracing ()) {
1119
- pyFrame = ensurePyFrame (virtualFrame , pyFrame );
1127
+ if (! noTrace . isValid () && threadState .getTraceFun () != null && !threadState .isTracing ()) {
1128
+ mutableData . pyFrame = ensurePyFrame (virtualFrame , mutableData . pyFrame );
1120
1129
int thisLine = bciToLine (bci );
1121
- boolean onANewLine = thisLine != pastLine ;
1122
- pastLine = thisLine ;
1123
- OpCodes c = OpCodes .fromOpCode (localBC [pastBci ]);
1130
+ boolean onANewLine = thisLine != mutableData . pastLine ;
1131
+ mutableData . pastLine = thisLine ;
1132
+ OpCodes c = OpCodes .fromOpCode (localBC [mutableData . pastBci ]);
1124
1133
/*
1125
1134
* normally, we trace a line every time the previous bytecode instruction was on a
1126
1135
* different line than the current one. There are a number of exceptions to this,
@@ -1138,26 +1147,26 @@ private Object bytecodeLoop(VirtualFrame virtualFrame, Frame localFrame, Bytecod
1138
1147
* https://github.com/python/cpython/blob/main/Objects/lnotab_notes.txt#L210-L215
1139
1148
* for more details
1140
1149
*/
1141
- boolean shouldTrace = pyFrame .getLocalTraceFun () != null && pyFrame .getTraceLine ();
1150
+ boolean shouldTrace = mutableData . pyFrame .getLocalTraceFun () != null && mutableData . pyFrame .getTraceLine ();
1142
1151
if (shouldTrace ) {
1143
- shouldTrace = pastBci > bci ; // is a backward jump
1152
+ shouldTrace = mutableData . pastBci > bci ; // is a backward jump
1144
1153
if (!shouldTrace ) {
1145
1154
shouldTrace = onANewLine &&
1146
1155
// is not a forward jump
1147
- (pastBci + c .length () >= bci ||
1156
+ (mutableData . pastBci + c .length () >= bci ||
1148
1157
// is a forward jump to the start of line
1149
1158
bciToLine (bci - 1 ) != thisLine );
1150
1159
}
1151
1160
}
1152
1161
if (shouldTrace ) {
1153
- returnLine = pastLine ;
1154
- pyFrame .setLocalTraceFun (
1155
- invokeTraceFunction (pyFrame .getLocalTraceFun (), null , threadState , virtualFrame , pyFrame , PythonContext .TraceEvent .LINE ,
1156
- pastLine ));
1162
+ mutableData . returnLine = mutableData . pastLine ;
1163
+ mutableData . pyFrame .setLocalTraceFun (
1164
+ invokeTraceFunction (mutableData . pyFrame .getLocalTraceFun (), null , threadState , virtualFrame , mutableData . pyFrame , PythonContext .TraceEvent .LINE ,
1165
+ mutableData . pastLine ));
1157
1166
}
1158
1167
}
1159
- if (threadState .getTraceFun () != null ) {
1160
- pastBci = bci ;
1168
+ if (! noTrace . isValid () && threadState .getTraceFun () != null ) {
1169
+ mutableData . pastBci = bci ;
1161
1170
}
1162
1171
1163
1172
CompilerAsserts .partialEvaluationConstant (bc );
@@ -1613,11 +1622,11 @@ private Object bytecodeLoop(VirtualFrame virtualFrame, Frame localFrame, Bytecod
1613
1622
LoopNode .reportLoopCount (this , mutableData .loopCount );
1614
1623
}
1615
1624
Object value = virtualFrame .getObject (stackTop );
1616
- if (threadState .getTraceFun () != null && !threadState .isTracing ()) {
1617
- pyFrame = ensurePyFrame (virtualFrame , pyFrame );
1618
- if (pyFrame .getLocalTraceFun () != null ) {
1619
- invokeTraceFunction (pyFrame .getLocalTraceFun (), value , threadState , virtualFrame , pyFrame , PythonContext .TraceEvent .RETURN ,
1620
- pyFrame .getTraceLine () ? returnLine : bciToLine (bci ));
1625
+ if (! noTrace . isValid () && threadState .getTraceFun () != null && !threadState .isTracing ()) {
1626
+ mutableData . pyFrame = ensurePyFrame (virtualFrame , mutableData . pyFrame );
1627
+ if (mutableData . pyFrame .getLocalTraceFun () != null ) {
1628
+ invokeTraceFunction (mutableData . pyFrame .getLocalTraceFun (), value , threadState , virtualFrame , mutableData . pyFrame , PythonContext .TraceEvent .RETURN ,
1629
+ mutableData . pyFrame .getTraceLine () ? mutableData . returnLine : bciToLine (bci ));
1621
1630
}
1622
1631
}
1623
1632
if (isGeneratorOrCoroutine ) {
@@ -2058,11 +2067,11 @@ private Object bytecodeLoop(VirtualFrame virtualFrame, Frame localFrame, Bytecod
2058
2067
// Clear slots that were popped (if any)
2059
2068
clearFrameSlots (localFrame , stackTop + 1 , initialStackTop );
2060
2069
}
2061
- if (threadState .getTraceFun () != null && !threadState .isTracing ()) {
2062
- pyFrame = ensurePyFrame (virtualFrame , pyFrame );
2063
- if (pyFrame .getLocalTraceFun () != null ) {
2064
- invokeTraceFunction (pyFrame .getLocalTraceFun (), value , threadState , virtualFrame , pyFrame , PythonContext .TraceEvent .RETURN ,
2065
- pyFrame .getTraceLine () ? returnLine : bciToLine (bci ));
2070
+ if (! noTrace . isValid () && threadState .getTraceFun () != null && !threadState .isTracing ()) {
2071
+ mutableData . pyFrame = ensurePyFrame (virtualFrame , mutableData . pyFrame );
2072
+ if (mutableData . pyFrame .getLocalTraceFun () != null ) {
2073
+ invokeTraceFunction (mutableData . pyFrame .getLocalTraceFun (), value , threadState , virtualFrame , mutableData . pyFrame , PythonContext .TraceEvent .RETURN ,
2074
+ mutableData . pyFrame .getTraceLine () ? mutableData . returnLine : bciToLine (bci ));
2066
2075
}
2067
2076
}
2068
2077
return new GeneratorYieldResult (bci + 1 , stackTop , value );
@@ -2152,16 +2161,13 @@ private Object bytecodeLoop(VirtualFrame virtualFrame, Frame localFrame, Bytecod
2152
2161
}
2153
2162
}
2154
2163
2155
- if (threadState .getTraceFun () != null && !threadState .isTracing () && pe != null ) {
2156
- pyFrame = ensurePyFrame (virtualFrame , pyFrame );
2157
- if (pyFrame .getLocalTraceFun () != null ) {
2158
- if (traceGetExceptionTracebackNode == null ) {
2159
- CompilerDirectives .transferToInterpreterAndInvalidate ();
2160
- traceGetExceptionTracebackNode = insert (GetExceptionTracebackNode .create ());
2161
- }
2162
- Object traceback = traceGetExceptionTracebackNode .execute (pe );
2163
- pyFrame .setLocalTraceFun (invokeTraceFunction (pyFrame .getLocalTraceFun (),
2164
- factory .createTuple (new Object []{pe .getClass (), pe .setCatchingFrameAndGetEscapedException (virtualFrame , this ), traceback }), threadState , virtualFrame , pyFrame ,
2164
+ if (!noTrace .isValid () && threadState .getTraceFun () != null && !threadState .isTracing () && pe != null ) {
2165
+ mutableData .pyFrame = ensurePyFrame (virtualFrame , mutableData .pyFrame );
2166
+ if (mutableData .pyFrame .getLocalTraceFun () != null ) {
2167
+ Object traceback = GetExceptionTracebackNode .getUncached ().execute (pe );
2168
+ mutableData .pyFrame .setLocalTraceFun (invokeTraceFunction (mutableData .pyFrame .getLocalTraceFun (),
2169
+ factory .createTuple (new Object []{pe .getClass (), pe .setCatchingFrameAndGetEscapedException (virtualFrame , this ), traceback }), threadState , virtualFrame ,
2170
+ mutableData .pyFrame ,
2165
2171
PythonContext .TraceEvent .EXCEPTION , bciToLine (bci )));
2166
2172
}
2167
2173
}
@@ -2194,11 +2200,11 @@ private Object bytecodeLoop(VirtualFrame virtualFrame, Frame localFrame, Bytecod
2194
2200
if (CompilerDirectives .hasNextTier () && mutableData .loopCount > 0 ) {
2195
2201
LoopNode .reportLoopCount (this , mutableData .loopCount );
2196
2202
}
2197
- if (threadState .getTraceFun () != null ) {
2198
- pyFrame = ensurePyFrame (virtualFrame , pyFrame );
2199
- if (pyFrame .getLocalTraceFun () != null ) {
2200
- invokeTraceFunction (pyFrame .getLocalTraceFun (), PNone .NONE , threadState , virtualFrame , pyFrame , PythonContext .TraceEvent .RETURN ,
2201
- pyFrame .getTraceLine () ? returnLine : bciToLine (bci ));
2203
+ if (! noTrace . isValid () && threadState .getTraceFun () != null ) {
2204
+ mutableData . pyFrame = ensurePyFrame (virtualFrame , mutableData . pyFrame );
2205
+ if (mutableData . pyFrame .getLocalTraceFun () != null ) {
2206
+ invokeTraceFunction (mutableData . pyFrame .getLocalTraceFun (), PNone .NONE , threadState , virtualFrame , mutableData . pyFrame , PythonContext .TraceEvent .RETURN ,
2207
+ mutableData . pyFrame .getTraceLine () ? mutableData . returnLine : bciToLine (bci ));
2202
2208
}
2203
2209
}
2204
2210
if (e == pe ) {
@@ -2236,22 +2242,19 @@ private PFrame ensurePyFrame(VirtualFrame virtualFrame, PFrame pyFrame) {
2236
2242
return pyFrame ;
2237
2243
}
2238
2244
2245
+ @ HostCompilerDirectives .InliningCutoff
2239
2246
private Object invokeTraceFunction (Object traceFn , Object arg , PythonContext .PythonThreadState threadState , VirtualFrame virtualFrame , PFrame tracing ,
2240
2247
PythonContext .TraceEvent event , int line ) {
2241
2248
threadState .tracingStart (event );
2242
2249
Object nonNullArg = arg == null ? PNone .NONE : arg ;
2243
- if (traceCallTernaryMethodNode == null ) {
2244
- CompilerDirectives .transferToInterpreterAndInvalidate ();
2245
- traceCallTernaryMethodNode = insert (CallTernaryMethodNode .create ());
2246
- }
2247
2250
try {
2248
2251
if (line != -1 ) {
2249
2252
tracing .setLineLock (line );
2250
2253
}
2251
- Object result = traceCallTernaryMethodNode . execute (virtualFrame , traceFn , tracing , event .pythonName , nonNullArg );
2254
+ Object result = CallTernaryMethodNode . getUncached (). execute (null , traceFn , tracing , event .pythonName , nonNullArg );
2252
2255
return result == PNone .NONE ? null : result ;
2253
2256
} catch (Throwable e ) {
2254
- threadState .setTraceFun (null );
2257
+ threadState .setTraceFun (null , cachedLanguage );
2255
2258
throw e ;
2256
2259
} finally {
2257
2260
if (line != -1 ) {
0 commit comments