199
199
import com .oracle .truffle .api .CompilerDirectives .CompilationFinal ;
200
200
import com .oracle .truffle .api .CompilerDirectives .TruffleBoundary ;
201
201
import com .oracle .truffle .api .CompilerDirectives .ValueType ;
202
- import com .oracle .truffle .api .HostCompilerDirectives ;
203
202
import com .oracle .truffle .api .HostCompilerDirectives .BytecodeInterpreterSwitch ;
203
+ import com .oracle .truffle .api .HostCompilerDirectives .InliningCutoff ;
204
204
import com .oracle .truffle .api .Truffle ;
205
205
import com .oracle .truffle .api .TruffleLanguage ;
206
206
import com .oracle .truffle .api .TruffleSafepoint ;
@@ -1162,56 +1162,20 @@ private Object bytecodeLoop(VirtualFrame virtualFrame, Frame localFrame, Bytecod
1162
1162
CompilerAsserts .partialEvaluationConstant (bci );
1163
1163
CompilerAsserts .partialEvaluationConstant (stackTop );
1164
1164
1165
+ boolean tracingEnabled = isTracingEnabled (noTrace , mutableData );
1165
1166
// if we are simply continuing to run an OSR loop after the replacement, tracing an
1166
1167
// extra CALL event would be incorrect
1167
- if (!noTrace .isValid () && mutableData .getThreadState (this ).getTraceFun () != null && !fromOSR ) {
1168
- invokeTraceFunction (virtualFrame , null , mutableData .getThreadState (this ), mutableData , PythonContext .TraceEvent .CALL ,
1169
- initialBci == 0 ? getFirstLineno () : (mutableData .setPastLine (bciToLine (initialBci ))), false );
1168
+ if (tracingEnabled && !fromOSR ) {
1169
+ traceCall (virtualFrame , initialBci , mutableData );
1170
1170
}
1171
1171
1172
1172
int oparg = 0 ;
1173
1173
while (true ) {
1174
1174
final byte bc = localBC [bci ];
1175
1175
final int beginBci = bci ;
1176
- if (!noTrace .isValid () && mutableData .getThreadState (this ).getTraceFun () != null ) {
1177
- int thisLine = bciToLine (bci );
1178
- boolean onANewLine = thisLine != mutableData .getPastLine ();
1179
- mutableData .setPastLine (thisLine );
1180
- OpCodes c = OpCodes .fromOpCode (localBC [mutableData .getPastBci ()]);
1181
- /*
1182
- * normally, we trace a line every time the previous bytecode instruction was on a
1183
- * different line than the current one. There are a number of exceptions to this,
1184
- * notably around jumps:
1185
- *
1186
- * - When a backward jumps happens, a line is traced, even if it is the same as the
1187
- * previous one.
1188
- *
1189
- * - When a forward jump happens to the first bytecode instruction of a line, a line
1190
- * is traced.
1191
- *
1192
- * - When a forward jump happens to the middle of a line, a line is not traced.
1193
- *
1194
- * see
1195
- * https://github.com/python/cpython/blob/main/Objects/lnotab_notes.txt#L210-L215
1196
- * for more details
1197
- */
1198
- boolean shouldTrace = mutableData .getPastBci () > bci ; // is a backward jump
1199
- if (!shouldTrace ) {
1200
- shouldTrace = onANewLine &&
1201
- // is not a forward jump
1202
- (mutableData .getPastBci () + c .length () >= bci ||
1203
- // is a forward jump to the start of line
1204
- bciToLine (bci - 1 ) != thisLine );
1205
- }
1206
- if (shouldTrace ) {
1207
- mutableData .setReturnLine (mutableData .getPastLine ());
1208
- mutableData .setPyFrame (ensurePyFrame (virtualFrame , mutableData .getPyFrame ()));
1209
- if (mutableData .getPyFrame ().getTraceLine ()) {
1210
- invokeTraceFunction (virtualFrame , null , mutableData .getThreadState (this ), mutableData , PythonContext .TraceEvent .LINE ,
1211
- mutableData .getPastLine (), true );
1212
- }
1213
- }
1214
- mutableData .setPastBci (bci );
1176
+ tracingEnabled = isTracingEnabled (noTrace , mutableData );
1177
+ if (tracingEnabled ) {
1178
+ traceLine (virtualFrame , mutableData , localBC , bci );
1215
1179
}
1216
1180
1217
1181
CompilerAsserts .partialEvaluationConstant (bc );
@@ -1647,10 +1611,7 @@ private Object bytecodeLoop(VirtualFrame virtualFrame, Frame localFrame, Bytecod
1647
1611
}
1648
1612
case OpCodesConstants .BINARY_SUBSCR : {
1649
1613
setCurrentBci (virtualFrame , bciSlot , bci );
1650
- GetItemNode getItemNode = insertChildNode (localNodes , bci , GetItemNodeGen .class , NODE_GET_ITEM );
1651
- Object slice = virtualFrame .getObject (stackTop );
1652
- virtualFrame .setObject (stackTop --, null );
1653
- virtualFrame .setObject (stackTop , getItemNode .execute (virtualFrame , virtualFrame .getObject (stackTop ), slice ));
1614
+ stackTop = bytecodeBinarySubscr (virtualFrame , stackTop , bci , localNodes );
1654
1615
break ;
1655
1616
}
1656
1617
case OpCodesConstants .STORE_SUBSCR : {
@@ -1672,9 +1633,8 @@ private Object bytecodeLoop(VirtualFrame virtualFrame, Frame localFrame, Bytecod
1672
1633
LoopNode .reportLoopCount (this , mutableData .loopCount );
1673
1634
}
1674
1635
Object value = virtualFrame .getObject (stackTop );
1675
- if (!noTrace .isValid () && mutableData .getThreadState (this ).getTraceFun () != null ) {
1676
- invokeTraceFunction (virtualFrame , value , mutableData .getThreadState (this ), mutableData , PythonContext .TraceEvent .RETURN ,
1677
- mutableData .getReturnLine (), true );
1636
+ if (tracingEnabled ) {
1637
+ traceReturn (virtualFrame , mutableData , value );
1678
1638
}
1679
1639
if (isGeneratorOrCoroutine ) {
1680
1640
throw new GeneratorReturnException (value );
@@ -2114,9 +2074,8 @@ private Object bytecodeLoop(VirtualFrame virtualFrame, Frame localFrame, Bytecod
2114
2074
// Clear slots that were popped (if any)
2115
2075
clearFrameSlots (localFrame , stackTop + 1 , initialStackTop );
2116
2076
}
2117
- if (!noTrace .isValid () && mutableData .getThreadState (this ).getTraceFun () != null ) {
2118
- invokeTraceFunction (virtualFrame , value , mutableData .getThreadState (this ), mutableData , PythonContext .TraceEvent .RETURN ,
2119
- mutableData .getReturnLine (), true );
2077
+ if (tracingEnabled ) {
2078
+ traceYield (virtualFrame , mutableData , value );
2120
2079
}
2121
2080
return new GeneratorYieldResult (bci + 1 , stackTop , value );
2122
2081
}
@@ -2167,10 +2126,7 @@ private Object bytecodeLoop(VirtualFrame virtualFrame, Frame localFrame, Bytecod
2167
2126
}
2168
2127
}
2169
2128
case OpCodesConstants .PRINT_EXPR : {
2170
- setCurrentBci (virtualFrame , bciSlot , bci );
2171
- PrintExprNode printExprNode = insertChildNode (localNodes , beginBci , UNCACHED_PRINT_EXPR , PrintExprNodeGen .class , NODE_PRINT_EXPR , useCachedNodes );
2172
- printExprNode .execute (virtualFrame , virtualFrame .getObject (stackTop ));
2173
- virtualFrame .setObject (stackTop --, null );
2129
+ stackTop = bytecodePrintExpr (virtualFrame , useCachedNodes , stackTop , bci , localNodes , bciSlot , beginBci );
2174
2130
break ;
2175
2131
}
2176
2132
case OpCodesConstants .EXTENDED_ARG : {
@@ -2205,17 +2161,9 @@ private Object bytecodeLoop(VirtualFrame virtualFrame, Frame localFrame, Bytecod
2205
2161
}
2206
2162
}
2207
2163
2208
- if (!noTrace .isValid () && mutableData .getThreadState (this ).getTraceFun () != null && !mutableData .getThreadState (this ).isTracing () && pe != null ) {
2209
- mutableData .setPyFrame (ensurePyFrame (virtualFrame , mutableData .getPyFrame ()));
2210
- if (mutableData .getPyFrame ().getLocalTraceFun () != null ) {
2211
- Object traceback = GetExceptionTracebackNode .getUncached ().execute (pe );
2212
- PBaseException peForPython = pe .setCatchingFrameAndGetEscapedException (virtualFrame , this );
2213
- Object peType = GetClassNode .getUncached ().execute (peForPython );
2214
- invokeTraceFunction (virtualFrame ,
2215
- factory .createTuple (new Object []{peType , peForPython , traceback }), mutableData .getThreadState (this ),
2216
- mutableData ,
2217
- PythonContext .TraceEvent .EXCEPTION , bciToLine (bci ), true );
2218
- }
2164
+ tracingEnabled = isTracingEnabled (noTrace , mutableData );
2165
+ if (tracingEnabled && pe != null && !mutableData .getThreadState (this ).isTracing ()) {
2166
+ traceException (virtualFrame , mutableData , bci , pe );
2219
2167
}
2220
2168
2221
2169
int targetIndex = findHandler (beginBci );
@@ -2246,9 +2194,8 @@ private Object bytecodeLoop(VirtualFrame virtualFrame, Frame localFrame, Bytecod
2246
2194
if (CompilerDirectives .hasNextTier () && mutableData .loopCount > 0 ) {
2247
2195
LoopNode .reportLoopCount (this , mutableData .loopCount );
2248
2196
}
2249
- if (!noTrace .isValid () && mutableData .getThreadState (this ).getTraceFun () != null ) {
2250
- invokeTraceFunction (virtualFrame , PNone .NONE , mutableData .getThreadState (this ), mutableData , PythonContext .TraceEvent .RETURN ,
2251
- mutableData .getReturnLine (), true );
2197
+ if (tracingEnabled ) {
2198
+ traceReturn (virtualFrame , mutableData , PNone .NONE );
2252
2199
}
2253
2200
if (e == pe ) {
2254
2201
throw pe ;
@@ -2274,6 +2221,101 @@ private Object bytecodeLoop(VirtualFrame virtualFrame, Frame localFrame, Bytecod
2274
2221
}
2275
2222
}
2276
2223
2224
+ @ InliningCutoff // Used only to print expressions in interactive mode
2225
+ private int bytecodePrintExpr (VirtualFrame virtualFrame , boolean useCachedNodes , int stackTop , int bci , Node [] localNodes , int bciSlot , int beginBci ) {
2226
+ setCurrentBci (virtualFrame , bciSlot , bci );
2227
+ PrintExprNode printExprNode = insertChildNode (localNodes , beginBci , UNCACHED_PRINT_EXPR , PrintExprNodeGen .class , NODE_PRINT_EXPR , useCachedNodes );
2228
+ printExprNode .execute (virtualFrame , virtualFrame .getObject (stackTop ));
2229
+ virtualFrame .setObject (stackTop --, null );
2230
+ return stackTop ;
2231
+ }
2232
+
2233
+ private boolean isTracingEnabled (Assumption noTrace , MutableLoopData mutableData ) {
2234
+ return !noTrace .isValid () && mutableData .getThreadState (this ).getTraceFun () != null ;
2235
+ }
2236
+
2237
+ @ InliningCutoff
2238
+ private void traceYield (VirtualFrame virtualFrame , MutableLoopData mutableData , Object value ) {
2239
+ invokeTraceFunction (virtualFrame , value , mutableData .getThreadState (this ), mutableData , PythonContext .TraceEvent .RETURN ,
2240
+ mutableData .getReturnLine (), true );
2241
+ }
2242
+
2243
+ @ InliningCutoff
2244
+ private void traceReturn (VirtualFrame virtualFrame , MutableLoopData mutableData , Object value ) {
2245
+ invokeTraceFunction (virtualFrame , value , mutableData .getThreadState (this ), mutableData , PythonContext .TraceEvent .RETURN ,
2246
+ mutableData .getReturnLine (), true );
2247
+ }
2248
+
2249
+ @ InliningCutoff
2250
+ private void traceException (VirtualFrame virtualFrame , MutableLoopData mutableData , int bci , PException pe ) {
2251
+ mutableData .setPyFrame (ensurePyFrame (virtualFrame , mutableData .getPyFrame ()));
2252
+ if (mutableData .getPyFrame ().getLocalTraceFun () != null ) {
2253
+ Object traceback = GetExceptionTracebackNode .getUncached ().execute (pe );
2254
+ PBaseException peForPython = pe .setCatchingFrameAndGetEscapedException (virtualFrame , this );
2255
+ Object peType = GetClassNode .getUncached ().execute (peForPython );
2256
+ invokeTraceFunction (virtualFrame ,
2257
+ factory .createTuple (new Object []{peType , peForPython , traceback }), mutableData .getThreadState (this ),
2258
+ mutableData ,
2259
+ PythonContext .TraceEvent .EXCEPTION , bciToLine (bci ), true );
2260
+ }
2261
+ }
2262
+
2263
+ @ InliningCutoff
2264
+ private void traceCall (VirtualFrame virtualFrame , int initialBci , MutableLoopData mutableData ) {
2265
+ invokeTraceFunction (virtualFrame , null , mutableData .getThreadState (this ), mutableData , PythonContext .TraceEvent .CALL ,
2266
+ initialBci == 0 ? getFirstLineno () : (mutableData .setPastLine (bciToLine (initialBci ))), false );
2267
+ }
2268
+
2269
+ @ InliningCutoff
2270
+ private void traceLine (VirtualFrame virtualFrame , MutableLoopData mutableData , byte [] localBC , int bci ) {
2271
+ int thisLine = bciToLine (bci );
2272
+ boolean onANewLine = thisLine != mutableData .getPastLine ();
2273
+ mutableData .setPastLine (thisLine );
2274
+ OpCodes c = OpCodes .fromOpCode (localBC [mutableData .getPastBci ()]);
2275
+ /*
2276
+ * normally, we trace a line every time the previous bytecode instruction was on a different
2277
+ * line than the current one. There are a number of exceptions to this, notably around
2278
+ * jumps:
2279
+ *
2280
+ * - When a backward jumps happens, a line is traced, even if it is the same as the previous
2281
+ * one.
2282
+ *
2283
+ * - When a forward jump happens to the first bytecode instruction of a line, a line is
2284
+ * traced.
2285
+ *
2286
+ * - When a forward jump happens to the middle of a line, a line is not traced.
2287
+ *
2288
+ * see https://github.com/python/cpython/blob/main/Objects/lnotab_notes.txt#L210-L215 for
2289
+ * more details
2290
+ */
2291
+ boolean shouldTrace = mutableData .getPastBci () > bci ; // is a backward jump
2292
+ if (!shouldTrace ) {
2293
+ shouldTrace = onANewLine &&
2294
+ // is not a forward jump
2295
+ (mutableData .getPastBci () + c .length () >= bci ||
2296
+ // is a forward jump to the start of line
2297
+ bciToLine (bci - 1 ) != thisLine );
2298
+ }
2299
+ if (shouldTrace ) {
2300
+ mutableData .setReturnLine (mutableData .getPastLine ());
2301
+ mutableData .setPyFrame (ensurePyFrame (virtualFrame , mutableData .getPyFrame ()));
2302
+ if (mutableData .getPyFrame ().getTraceLine ()) {
2303
+ invokeTraceFunction (virtualFrame , null , mutableData .getThreadState (this ), mutableData , PythonContext .TraceEvent .LINE ,
2304
+ mutableData .getPastLine (), true );
2305
+ }
2306
+ }
2307
+ mutableData .setPastBci (bci );
2308
+ }
2309
+
2310
+ @ BytecodeInterpreterSwitch
2311
+ private int bytecodeBinarySubscr (VirtualFrame virtualFrame , int stackTop , int bci , Node [] localNodes ) {
2312
+ GetItemNode getItemNode = insertChildNode (localNodes , bci , GetItemNodeGen .class , NODE_GET_ITEM );
2313
+ Object slice = virtualFrame .getObject (stackTop );
2314
+ virtualFrame .setObject (stackTop --, null );
2315
+ virtualFrame .setObject (stackTop , getItemNode .execute (virtualFrame , virtualFrame .getObject (stackTop ), slice ));
2316
+ return stackTop ;
2317
+ }
2318
+
2277
2319
private PFrame ensurePyFrame (VirtualFrame virtualFrame , PFrame pyFrame ) {
2278
2320
if (traceMaterializeFrameNode == null ) {
2279
2321
CompilerDirectives .transferToInterpreterAndInvalidate ();
@@ -2285,7 +2327,6 @@ private PFrame ensurePyFrame(VirtualFrame virtualFrame, PFrame pyFrame) {
2285
2327
return pyFrame ;
2286
2328
}
2287
2329
2288
- @ HostCompilerDirectives .InliningCutoff
2289
2330
private void invokeTraceFunction (VirtualFrame virtualFrame , Object arg , PythonContext .PythonThreadState threadState , MutableLoopData mutableData ,
2290
2331
PythonContext .TraceEvent event , int line , boolean useLocalFn ) {
2291
2332
if (threadState .isTracing ()) {
0 commit comments