Haskell.org
Sign In Sign Up
Manage this list Sign In Sign Up

Keyboard Shortcuts

Thread View

  • j: Next unread message
  • k: Previous unread message
  • j a: Jump to all threads
  • j l: Jump to MailingList overview

ghc-commits

Thread Start a new thread
Download
Threads by month
  • ----- 2025 -----
  • July
  • June
  • May
  • April
  • March
  • February
  • January
ghc-commits@haskell.org

  • 1 participants
  • 1156 discussions
[Git][ghc/ghc][wip/romes/per-thread-step-in] debugger: Allow toggling step-in per thread
by Rodrigo Mesquita (@alt-romes) 20 May '25

20 May '25
Rodrigo Mesquita pushed to branch wip/romes/per-thread-step-in at Glasgow Haskell Compiler / GHC Commits: c44f60fd by Rodrigo Mesquita at 2025-05-20T16:54:12+01:00 debugger: Allow toggling step-in per thread The RTS global flag `rts_stop_next_breakpoint` globally sets the interpreter to stop at the immediate next breakpoint. With this commit, single step mode can additionally be set per thread in the TSO flag (TSO_STOP_NEXT_BREAKPOINT). Being able to toggle "stop at next breakpoint" per thread is an important requirement for implementing "stepping out" of a function in a multi-threaded context. And, more generally, having a per-thread flag for single-stepping paves the way for multi-threaded debugging. That said, when we want to enable "single step" mode for the whole interpreted program we still want to stop at the immediate next breakpoint, whichever thread it belongs to. That's why we also keep the global `rts_stop_next_breakpoint` flag, with `rts_enableStopNextBreakpointAll` and `rts_disableStopNextBreakpointAll` helpers. Preparation for #26042 - - - - - 9 changed files: - libraries/ghc-heap/GHC/Exts/Heap/Closures.hs - libraries/ghc-heap/GHC/Exts/Heap/FFIClosures_ProfilingDisabled.hsc - libraries/ghc-heap/GHC/Exts/Heap/FFIClosures_ProfilingEnabled.hsc - libraries/ghc-heap/tests/parse_tso_flags.hs - libraries/ghci/GHCi/Run.hs - rts/Interpreter.c - rts/Interpreter.h - rts/RtsSymbols.c - rts/include/rts/Constants.h Changes: ===================================== libraries/ghc-heap/GHC/Exts/Heap/Closures.hs ===================================== @@ -624,6 +624,7 @@ data TsoFlags | TsoMarked | TsoSqueezed | TsoAllocLimit + | TsoStopNextBreakpoint | TsoFlagsUnknownValue Word32 -- ^ Please report this as a bug deriving (Eq, Show, Generic, Ord) ===================================== libraries/ghc-heap/GHC/Exts/Heap/FFIClosures_ProfilingDisabled.hsc ===================================== @@ -87,6 +87,9 @@ parseTsoFlags w | isSet (#const TSO_LOCKED) w = TsoLocked : parseTsoFlags (unset | isSet (#const TSO_MARKED) w = TsoMarked : parseTsoFlags (unset (#const TSO_MARKED) w) | isSet (#const TSO_SQUEEZED) w = TsoSqueezed : parseTsoFlags (unset (#const TSO_SQUEEZED) w) | isSet (#const TSO_ALLOC_LIMIT) w = TsoAllocLimit : parseTsoFlags (unset (#const TSO_ALLOC_LIMIT) w) +#if __GLASGOW_HASKELL__ >= 913 + | isSet (#const TSO_STOP_NEXT_BREAKPOINT) w = TsoStopNextBreakpoint : parseTsoFlags (unset (#const TSO_STOP_NEXT_BREAKPOINT) w) +#endif parseTsoFlags 0 = [] parseTsoFlags w = [TsoFlagsUnknownValue w] ===================================== libraries/ghc-heap/GHC/Exts/Heap/FFIClosures_ProfilingEnabled.hsc ===================================== @@ -87,6 +87,9 @@ parseTsoFlags w | isSet (#const TSO_LOCKED) w = TsoLocked : parseTsoFlags (unset | isSet (#const TSO_MARKED) w = TsoMarked : parseTsoFlags (unset (#const TSO_MARKED) w) | isSet (#const TSO_SQUEEZED) w = TsoSqueezed : parseTsoFlags (unset (#const TSO_SQUEEZED) w) | isSet (#const TSO_ALLOC_LIMIT) w = TsoAllocLimit : parseTsoFlags (unset (#const TSO_ALLOC_LIMIT) w) +#if __GLASGOW_HASKELL__ >= 913 + | isSet (#const TSO_STOP_NEXT_BREAKPOINT) w = TsoStopNextBreakpoint : parseTsoFlags (unset (#const TSO_STOP_NEXT_BREAKPOINT) w) +#endif parseTsoFlags 0 = [] parseTsoFlags w = [TsoFlagsUnknownValue w] ===================================== libraries/ghc-heap/tests/parse_tso_flags.hs ===================================== @@ -13,5 +13,6 @@ main = do assertEqual (parseTsoFlags 64) [TsoMarked] assertEqual (parseTsoFlags 128) [TsoSqueezed] assertEqual (parseTsoFlags 256) [TsoAllocLimit] + assertEqual (parseTsoFlags 512) [TsoStopNextBreakpoint] assertEqual (parseTsoFlags 6) [TsoLocked, TsoBlockx] ===================================== libraries/ghci/GHCi/Run.hs ===================================== @@ -1,5 +1,5 @@ {-# LANGUAGE GADTs, RecordWildCards, MagicHash, ScopedTypeVariables, CPP, - UnboxedTuples, LambdaCase #-} + UnboxedTuples, LambdaCase, UnliftedFFITypes #-} {-# OPTIONS_GHC -fno-warn-name-shadowing #-} -- | @@ -396,13 +396,21 @@ abandonStmt hvref = do _ <- takeMVar resumeStatusMVar return () -foreign import ccall "&rts_stop_next_breakpoint" stepFlag :: Ptr CInt +foreign import ccall unsafe "rts_enableStopNextBreakpointAll" + rts_enableStopNextBreakpointAll :: IO () + +foreign import ccall unsafe "rts_disableStopNextBreakpointAll" + rts_disableStopNextBreakpointAll :: IO () + foreign import ccall "&rts_stop_on_exception" exceptionFlag :: Ptr CInt +-- | Enables the single step mode for all threads, thus stopping at any +-- existing breakpoint. setStepFlag :: IO () -setStepFlag = poke stepFlag 1 +setStepFlag = rts_enableStopNextBreakpointAll + resetStepFlag :: IO () -resetStepFlag = poke stepFlag 0 +resetStepFlag = rts_disableStopNextBreakpointAll type BreakpointCallback = Addr# -- pointer to the breakpoint tick module name ===================================== rts/Interpreter.c ===================================== @@ -243,9 +243,25 @@ allocate_NONUPD (Capability *cap, int n_words) return allocate(cap, stg_max(sizeofW(StgHeader)+MIN_PAYLOAD_SIZE, n_words)); } +// A global toggle for single-step mode. +// Unlike `TSO_STOP_NEXT_BREAKPOINT`, which sets single-step mode per-thread, +// `rts_stop_next_breakpoint` globally enables single-step mode. If enabled, we +// will stop at the immediate next breakpoint regardless of what thread it is in. int rts_stop_next_breakpoint = 0; int rts_stop_on_exception = 0; +// Enable the global single step mode +void rts_enableStopNextBreakpointAll() +{ + rts_stop_next_breakpoint = 1; +} + +// Disable the global single step mode +void rts_disableStopNextBreakpointAll() +{ + rts_stop_next_breakpoint = 0; +} + #if defined(INTERP_STATS) #define N_CODES 128 @@ -1250,7 +1266,7 @@ run_BCO: int arg8_cc; #endif StgArrBytes *breakPoints; - int returning_from_break; + int returning_from_break, stop_next_breakpoint; // the io action to run at a breakpoint StgClosure *ioAction; @@ -1280,6 +1296,13 @@ run_BCO: returning_from_break = cap->r.rCurrentTSO->flags & TSO_STOPPED_ON_BREAKPOINT; + // check whether this thread is set to stop at the immediate next + // breakpoint -- either by the global `rts_stop_next_breakpoint` + // flag, or by the local `TSO_STOP_NEXT_BREAKPOINT` + stop_next_breakpoint = + rts_stop_next_breakpoint || + cap->r.rCurrentTSO->flags & TSO_STOP_NEXT_BREAKPOINT; + #if defined(PROFILING) cap->r.rCCCS = pushCostCentre(cap->r.rCCCS, (CostCentre*)BCO_LIT(arg8_cc)); @@ -1291,20 +1314,20 @@ run_BCO: { breakPoints = (StgArrBytes *) BCO_PTR(arg1_brk_array); - // stop the current thread if either the - // "rts_stop_next_breakpoint" flag is true OR if the - // ignore count for this particular breakpoint is zero + // stop the current thread if either `stop_next_breakpoint` is + // true OR if the ignore count for this particular breakpoint is zero StgInt ignore_count = ((StgInt*)breakPoints->payload)[arg6_tick_index]; - if (rts_stop_next_breakpoint == false && ignore_count > 0) + if (stop_next_breakpoint == false && ignore_count > 0) { // decrement and write back ignore count ((StgInt*)breakPoints->payload)[arg6_tick_index] = --ignore_count; } - else if (rts_stop_next_breakpoint == true || ignore_count == 0) + else if (stop_next_breakpoint == true || ignore_count == 0) { // make sure we don't automatically stop at the // next breakpoint - rts_stop_next_breakpoint = false; + rts_stop_next_breakpoint = 0; + cap->r.rCurrentTSO->flags &= ~TSO_STOP_NEXT_BREAKPOINT; // allocate memory for a new AP_STACK, enough to // store the top stack frame plus an ===================================== rts/Interpreter.h ===================================== @@ -11,3 +11,6 @@ RTS_PRIVATE Capability *interpretBCO (Capability* cap); void interp_startup ( void ); void interp_shutdown ( void ); + +void rts_enableStopNextBreakpointAll ( void ); +void rts_disableStopNextBreakpointAll ( void ); ===================================== rts/RtsSymbols.c ===================================== @@ -906,7 +906,8 @@ extern char **environ; SymI_HasProto(revertCAFs) \ SymI_HasProto(RtsFlags) \ SymI_NeedsDataProto(rts_breakpoint_io_action) \ - SymI_NeedsDataProto(rts_stop_next_breakpoint) \ + SymI_NeedsDataProto(rts_enableStopNextBreakpointAll) \ + SymI_NeedsDataProto(rts_disableStopNextBreakpointAll) \ SymI_NeedsDataProto(rts_stop_on_exception) \ SymI_HasProto(stopTimer) \ SymI_HasProto(n_capabilities) \ ===================================== rts/include/rts/Constants.h ===================================== @@ -328,6 +328,12 @@ */ #define TSO_ALLOC_LIMIT 256 +/* + * Enables step-in mode for this thread -- it will stop at the immediate next + * breakpoint found in this thread. + */ +#define TSO_STOP_NEXT_BREAKPOINT 512 + /* * The number of times we spin in a spin lock before yielding (see * #3758). To tune this value, use the benchmark in #3758: run the View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/c44f60fda04f7e6e9a70318d107d41c… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/c44f60fda04f7e6e9a70318d107d41c… You're receiving this email because of your account on gitlab.haskell.org.
1 0
0 0
[Git][ghc/ghc][wip/marge_bot_batch_merge_job] 14 commits: Track rewriter sets more accurately in constraint solving
by Marge Bot (@marge-bot) 20 May '25

20 May '25
Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC Commits: ac9fb269 by Simon Peyton Jones at 2025-05-20T09:19:04-04:00 Track rewriter sets more accurately in constraint solving This MR addresses #26003, by refactoring the arcane intricacies of Note [Equalities with incompatible kinds]. NB: now retitled to Note [Equalities with heterogeneous kinds]. and the main Note for this MR. In particular: * Abandon invariant (COERCION-HOLE) in Note [Unification preconditions] in GHC.Tc.Utils.Unify. * Abandon invariant (TyEq:CH)) in Note [Canonical equalities] in GHC.Tc.Types.Constraint. * Instead: add invariant (REWRITERS) to Note [Unification preconditions]: unify only if the constraint has an empty rewriter set. Implementation: * In canEqCanLHSFinish_try_unification, skip trying unification if there is a non-empty rewriter set. * To do this, make sure the rewriter set is zonked; do so in selectNextWorkItem, which also deals with prioritisation. * When a coercion hole is filled, kick out inert equalities that have that hole as a rewriter. It might now be unlocked and available to unify. * Remove the ad-hoc `ch_hetero_kind` field of `CoercionHole`. * In `selectNextWorkItem`, priorities equalities withan empty rewriter set. * Defaulting: see (DE6) in Note [Defaulting equalities] and Note [Limited defaulting in the ambiguity check] * Concreteness checks: there is some extra faff to try to get decent error messages when the FRR (representation-polymorphism) checks fail. In partiular, add a "When unifying..." explanation when the representation-polymorphism check arose from another constraint. - - - - - 86406f48 by Cheng Shao at 2025-05-20T09:19:47-04:00 rts: fix rts_clearMemory logic when sanity checks are enabled This commit fixes an RTS assertion failure when invoking rts_clearMemory with +RTS -DS. -DS implies -DZ which asserts that free blocks contain 0xaa as the designated garbage value. Also adds the sanity way to rts_clearMemory test to prevent future regression. Closes #26011. ChatGPT Codex automatically diagnosed the issue and proposed the initial patch in a single shot, given a GHC checkout and the following prompt: --- Someone is reporting the following error when attempting to use `rts_clearMemory` with the RTS option `-DS`: ``` test.wasm: internal error: ASSERTION FAILED: file rts/sm/Storage.c, line 1216 (GHC version 9.12.2.20250327 for wasm32_unknown_wasi) Please report this as a GHC bug: https://www.haskell.org/ghc/reportabug ``` What's the culprit? How do I look into this issue? --- I manually reviewed & revised the patch, tested and submitted it. - - - - - 2b795c2f by Cheng Shao at 2025-05-20T09:51:24-04:00 compiler: do not allocate strings in bytecode assembler This patch refactors the compiler to avoid allocating iserv buffers for BCONPtrStr at assemble-time. Now BCONPtrStr ByteStrings are recorded as a part of CompiledByteCode, and actual allocation only happens at link-time. This refactoring is necessary for adding bytecode serialization functionality, as explained by the revised comments in this commit. - - - - - 2914d829 by Cheng Shao at 2025-05-20T09:51:24-04:00 compiler: make bc_strs serializable This commit makes the bc_strs field in CompiledByteCode serializable; similar to previous commit, we preserve the ByteString directly and defer the actual allocation to link-time, as mentioned in updated comment. - - - - - a6ec1765 by Cheng Shao at 2025-05-20T09:51:24-04:00 compiler: make bc_itbls serializable This commit makes bc_itbls in CompiledByteCode serializable. A dedicated ConInfoTable datatype has been added in ghci which is the recipe for dynamically making a datacon's info table, containing the payload of the MkConInfoTable iserv message. - - - - - a238a259 by Cheng Shao at 2025-05-20T09:51:24-04:00 compiler: remove FFIInfo bookkeeping in BCO This commit removes the bc_ffis field from CompiledByteCode completely, as well as all the related bookkeeping logic in GHC.StgToByteCode. bc_ffis is actually *unused* in the rest of GHC codebase! It is merely a list of FFIInfo, which is just a remote pointer of the libffi ffi_cif struct; once we allocate the ffi_cif struct and put its pointer in a CCALL instruction, we'll never free it anyway. So there is no point of bookkeeping. - - - - - 1f5cc26b by Cheng Shao at 2025-05-20T09:51:24-04:00 compiler: make FFIInfo serializable in BCO This commit makes all the FFIInfo needed in CCALL instructions serializable. Previously, when doing STG to BCO lowering, we would allocate a libffi ffi_cif struct and keep its remote pointer as FFIInfo; but actually we can just keep the type signature as FFIInfo and defer the actual allocation to link-time. - - - - - 20a60364 by Cheng Shao at 2025-05-20T09:51:24-04:00 ghci: remove redundant NewBreakModule message This commit removes the redundant NewBreakModule message from ghci: it just allocates two strings! This functionality can be implemented with existing MallocStrings in one iserv call. - - - - - bbfd5a5c by Cheng Shao at 2025-05-20T09:51:24-04:00 compiler: make breakpoint module name and unit id serializable This commit makes breakpoint module name and unit id serializable, in BRK_FUN instructions as well as ModBreaks. We can simply keep the module name and unit ids, and defer the buffer allocation to link time. - - - - - aaaf4576 by Cheng Shao at 2025-05-20T09:51:24-04:00 compiler: remove unused newModule This commit removes the now unused newModule function from GHC. - - - - - ea0f5482 by Cheng Shao at 2025-05-20T09:51:24-04:00 compiler: add BCONPtrFS for interned top level string literals in BCO This commit adds BCONPtrFS as a BCO non-pointer literal kind, which has the same semantics of BCONPtrStr, except it contains a FastString instead of a ByteString. By using BCONPtrFS to represent top level string literals that are already FastString in the compilation pipeline, we enjoy the FastString interning logic and avoid allocating a bunch of redundant ByteStrings for the same FastStrings, especially when we lower the BRK_FUN instruction. - - - - - 55b0dfd8 by Peng Fan at 2025-05-20T09:51:36-04:00 hadrian: enable GHCi for loongarch64 - - - - - 6c1c9110 by kwxm at 2025-05-20T09:51:45-04:00 Fix bugs in `integerRecipMod` and `integerPowMod` This fixes #26017. * `integerRecipMod x 1` now returns `(# 1 | #)` for all x; previously it incorrectly returned `(# | () #)`, indicating failure. * `integerPowMod 0 e m` now returns `(# | () #)` for e<0 and m>1, indicating failure; previously it incorrectly returned `(# 0 | #)`. - - - - - 0155f550 by Andreas Klebinger at 2025-05-20T09:51:46-04:00 Specialise: Don't float out constraint components. It was fairly complex to do so and it doesn't seem to improve anything. Nofib allocations were unaffected as well. See also Historical Note [Floating dictionaries out of cases] - - - - - 89 changed files: - compiler/GHC/ByteCode/Asm.hs - compiler/GHC/ByteCode/InfoTable.hs - compiler/GHC/ByteCode/Instr.hs - compiler/GHC/ByteCode/Linker.hs - compiler/GHC/ByteCode/Types.hs - compiler/GHC/Core/Coercion.hs - compiler/GHC/Core/Opt/Specialise.hs - compiler/GHC/Core/Predicate.hs - compiler/GHC/Core/TyCo/Rep.hs - compiler/GHC/Core/TyCo/Tidy.hs - compiler/GHC/HsToCore/Breakpoints.hs - compiler/GHC/Linker/Loader.hs - compiler/GHC/Runtime/Interpreter.hs - compiler/GHC/StgToByteCode.hs - compiler/GHC/Tc/Errors.hs - compiler/GHC/Tc/Errors/Ppr.hs - compiler/GHC/Tc/Errors/Types.hs - compiler/GHC/Tc/Gen/HsType.hs - compiler/GHC/Tc/Plugin.hs - compiler/GHC/Tc/Solver.hs - compiler/GHC/Tc/Solver/Default.hs - compiler/GHC/Tc/Solver/Equality.hs - compiler/GHC/Tc/Solver/InertSet.hs - compiler/GHC/Tc/Solver/Monad.hs - compiler/GHC/Tc/Types/Constraint.hs - compiler/GHC/Tc/Utils/TcMType.hs - compiler/GHC/Tc/Utils/Unify.hs - compiler/GHC/Tc/Zonk/TcType.hs - compiler/GHC/Types/Error/Codes.hs - hadrian/src/Oracles/Flag.hs - libraries/base/changelog.md - libraries/ghc-internal/src/GHC/Internal/Bignum/Integer.hs - libraries/ghci/GHCi/Message.hs - libraries/ghci/GHCi/Run.hs - rts/sm/Storage.h - testsuite/tests/bytecode/T22376/all.T - testsuite/tests/dependent/should_fail/T11471.stderr - testsuite/tests/diagnostic-codes/codes.stdout - testsuite/tests/ffi/should_run/all.T - testsuite/tests/indexed-types/should_fail/T8227.stderr - testsuite/tests/indexed-types/should_fail/T9662.stderr - + testsuite/tests/lib/integer/T26017.hs - + testsuite/tests/lib/integer/T26017.stdout - testsuite/tests/lib/integer/all.T - testsuite/tests/lib/integer/integerRecipMod.hs - testsuite/tests/lib/integer/integerRecipMod.stdout - testsuite/tests/partial-sigs/should_fail/T14040a.stderr - testsuite/tests/partial-sigs/should_fail/T14584.stderr - testsuite/tests/perf/should_run/ByteCodeAsm.hs - testsuite/tests/polykinds/T14172.stderr - testsuite/tests/polykinds/T14846.stderr - testsuite/tests/rep-poly/RepPolyArgument.stderr - testsuite/tests/rep-poly/RepPolyBackpack1.stderr - testsuite/tests/rep-poly/RepPolyBinder.stderr - testsuite/tests/rep-poly/RepPolyDoBind.stderr - testsuite/tests/rep-poly/RepPolyDoBody1.stderr - testsuite/tests/rep-poly/RepPolyDoBody2.stderr - testsuite/tests/rep-poly/RepPolyLeftSection2.stderr - testsuite/tests/rep-poly/RepPolyMagic.stderr - testsuite/tests/rep-poly/RepPolyMcBind.stderr - testsuite/tests/rep-poly/RepPolyMcBody.stderr - testsuite/tests/rep-poly/RepPolyMcGuard.stderr - testsuite/tests/rep-poly/RepPolyNPlusK.stderr - testsuite/tests/rep-poly/RepPolyPatBind.stderr - testsuite/tests/rep-poly/RepPolyRecordUpdate.stderr - testsuite/tests/rep-poly/RepPolyRightSection.stderr - testsuite/tests/rep-poly/RepPolyRule1.stderr - testsuite/tests/rep-poly/RepPolyTuple.stderr - testsuite/tests/rep-poly/RepPolyTuple4.stderr - testsuite/tests/rep-poly/RepPolyTupleSection.stderr - testsuite/tests/rep-poly/RepPolyWrappedVar.stderr - testsuite/tests/rep-poly/T11473.stderr - testsuite/tests/rep-poly/T12709.stderr - testsuite/tests/rep-poly/T12973.stderr - testsuite/tests/rep-poly/T13233.stderr - testsuite/tests/rep-poly/T13929.stderr - testsuite/tests/rep-poly/T14561.stderr - testsuite/tests/rep-poly/T14561b.stderr - testsuite/tests/rep-poly/T17817.stderr - testsuite/tests/rep-poly/T19615.stderr - testsuite/tests/rep-poly/T19709b.stderr - testsuite/tests/rep-poly/T21906.stderr - testsuite/tests/rep-poly/T23903.stderr - testsuite/tests/rep-poly/UnliftedNewtypesCoerceFail.stderr - testsuite/tests/typecheck/no_skolem_info/T14040.stderr - testsuite/tests/typecheck/should_compile/T25266a.stderr - testsuite/tests/typecheck/should_fail/T16204c.stderr - testsuite/tests/typecheck/should_fail/T7696.stderr - testsuite/tests/typecheck/should_fail/T8603.stderr The diff was not included because it is too large. View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/482c7ce093c840e0e657f96f705efa… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/482c7ce093c840e0e657f96f705efa… You're receiving this email because of your account on gitlab.haskell.org.
1 0
0 0
[Git][ghc/ghc][master] rts: fix rts_clearMemory logic when sanity checks are enabled
by Marge Bot (@marge-bot) 20 May '25

20 May '25
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC Commits: 86406f48 by Cheng Shao at 2025-05-20T09:19:47-04:00 rts: fix rts_clearMemory logic when sanity checks are enabled This commit fixes an RTS assertion failure when invoking rts_clearMemory with +RTS -DS. -DS implies -DZ which asserts that free blocks contain 0xaa as the designated garbage value. Also adds the sanity way to rts_clearMemory test to prevent future regression. Closes #26011. ChatGPT Codex automatically diagnosed the issue and proposed the initial patch in a single shot, given a GHC checkout and the following prompt: --- Someone is reporting the following error when attempting to use `rts_clearMemory` with the RTS option `-DS`: ``` test.wasm: internal error: ASSERTION FAILED: file rts/sm/Storage.c, line 1216 (GHC version 9.12.2.20250327 for wasm32_unknown_wasi) Please report this as a GHC bug: https://www.haskell.org/ghc/reportabug ``` What's the culprit? How do I look into this issue? --- I manually reviewed & revised the patch, tested and submitted it. - - - - - 2 changed files: - rts/sm/Storage.h - testsuite/tests/ffi/should_run/all.T Changes: ===================================== rts/sm/Storage.h ===================================== @@ -213,7 +213,8 @@ extern StgIndStatic * debug_caf_list; extern StgIndStatic * revertible_caf_list; INLINE_HEADER void clear_blocks(bdescr *bd) { - memset(bd->start, 0, BLOCK_SIZE * bd->blocks); + memset(bd->start, RtsFlags.DebugFlags.zero_on_gc ? 0xaa : 0, + BLOCK_SIZE * bd->blocks); } #include "EndPrivate.h" ===================================== testsuite/tests/ffi/should_run/all.T ===================================== @@ -188,8 +188,8 @@ test('ffi023', [ omit_ghci, test('rts_clearMemory', [ # We only care about different GC configurations under the # single-threaded RTS for the time being. - only_ways(['normal', 'optasm' ,'g1', 'nursery_chunks', 'nonmoving', 'compacting_gc']), - extra_ways(['g1', 'nursery_chunks', 'nonmoving', 'compacting_gc']), + only_ways(['normal', 'optasm' ,'g1', 'nursery_chunks', 'nonmoving', 'compacting_gc', 'sanity']), + extra_ways(['g1', 'nursery_chunks', 'nonmoving', 'compacting_gc', 'sanity']), # On windows, nonmoving way fails with bad exit code (2816) when(opsys('mingw32'), fragile(23091)), req_c, View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/86406f48659a5ab61ce1fd2a2d427fa… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/86406f48659a5ab61ce1fd2a2d427fa… You're receiving this email because of your account on gitlab.haskell.org.
1 0
0 0
[Git][ghc/ghc][master] Track rewriter sets more accurately in constraint solving
by Marge Bot (@marge-bot) 20 May '25

20 May '25
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC Commits: ac9fb269 by Simon Peyton Jones at 2025-05-20T09:19:04-04:00 Track rewriter sets more accurately in constraint solving This MR addresses #26003, by refactoring the arcane intricacies of Note [Equalities with incompatible kinds]. NB: now retitled to Note [Equalities with heterogeneous kinds]. and the main Note for this MR. In particular: * Abandon invariant (COERCION-HOLE) in Note [Unification preconditions] in GHC.Tc.Utils.Unify. * Abandon invariant (TyEq:CH)) in Note [Canonical equalities] in GHC.Tc.Types.Constraint. * Instead: add invariant (REWRITERS) to Note [Unification preconditions]: unify only if the constraint has an empty rewriter set. Implementation: * In canEqCanLHSFinish_try_unification, skip trying unification if there is a non-empty rewriter set. * To do this, make sure the rewriter set is zonked; do so in selectNextWorkItem, which also deals with prioritisation. * When a coercion hole is filled, kick out inert equalities that have that hole as a rewriter. It might now be unlocked and available to unify. * Remove the ad-hoc `ch_hetero_kind` field of `CoercionHole`. * In `selectNextWorkItem`, priorities equalities withan empty rewriter set. * Defaulting: see (DE6) in Note [Defaulting equalities] and Note [Limited defaulting in the ambiguity check] * Concreteness checks: there is some extra faff to try to get decent error messages when the FRR (representation-polymorphism) checks fail. In partiular, add a "When unifying..." explanation when the representation-polymorphism check arose from another constraint. - - - - - 65 changed files: - compiler/GHC/Core/Coercion.hs - compiler/GHC/Core/Predicate.hs - compiler/GHC/Core/TyCo/Rep.hs - compiler/GHC/Core/TyCo/Tidy.hs - compiler/GHC/Tc/Errors.hs - compiler/GHC/Tc/Errors/Ppr.hs - compiler/GHC/Tc/Errors/Types.hs - compiler/GHC/Tc/Gen/HsType.hs - compiler/GHC/Tc/Plugin.hs - compiler/GHC/Tc/Solver.hs - compiler/GHC/Tc/Solver/Default.hs - compiler/GHC/Tc/Solver/Equality.hs - compiler/GHC/Tc/Solver/InertSet.hs - compiler/GHC/Tc/Solver/Monad.hs - compiler/GHC/Tc/Types/Constraint.hs - compiler/GHC/Tc/Utils/TcMType.hs - compiler/GHC/Tc/Utils/Unify.hs - compiler/GHC/Tc/Zonk/TcType.hs - compiler/GHC/Types/Error/Codes.hs - testsuite/tests/dependent/should_fail/T11471.stderr - testsuite/tests/diagnostic-codes/codes.stdout - testsuite/tests/indexed-types/should_fail/T8227.stderr - testsuite/tests/indexed-types/should_fail/T9662.stderr - testsuite/tests/partial-sigs/should_fail/T14040a.stderr - testsuite/tests/partial-sigs/should_fail/T14584.stderr - testsuite/tests/polykinds/T14172.stderr - testsuite/tests/polykinds/T14846.stderr - testsuite/tests/rep-poly/RepPolyArgument.stderr - testsuite/tests/rep-poly/RepPolyBackpack1.stderr - testsuite/tests/rep-poly/RepPolyBinder.stderr - testsuite/tests/rep-poly/RepPolyDoBind.stderr - testsuite/tests/rep-poly/RepPolyDoBody1.stderr - testsuite/tests/rep-poly/RepPolyDoBody2.stderr - testsuite/tests/rep-poly/RepPolyLeftSection2.stderr - testsuite/tests/rep-poly/RepPolyMagic.stderr - testsuite/tests/rep-poly/RepPolyMcBind.stderr - testsuite/tests/rep-poly/RepPolyMcBody.stderr - testsuite/tests/rep-poly/RepPolyMcGuard.stderr - testsuite/tests/rep-poly/RepPolyNPlusK.stderr - testsuite/tests/rep-poly/RepPolyPatBind.stderr - testsuite/tests/rep-poly/RepPolyRecordUpdate.stderr - testsuite/tests/rep-poly/RepPolyRightSection.stderr - testsuite/tests/rep-poly/RepPolyRule1.stderr - testsuite/tests/rep-poly/RepPolyTuple.stderr - testsuite/tests/rep-poly/RepPolyTuple4.stderr - testsuite/tests/rep-poly/RepPolyTupleSection.stderr - testsuite/tests/rep-poly/RepPolyWrappedVar.stderr - testsuite/tests/rep-poly/T11473.stderr - testsuite/tests/rep-poly/T12709.stderr - testsuite/tests/rep-poly/T12973.stderr - testsuite/tests/rep-poly/T13233.stderr - testsuite/tests/rep-poly/T13929.stderr - testsuite/tests/rep-poly/T14561.stderr - testsuite/tests/rep-poly/T14561b.stderr - testsuite/tests/rep-poly/T17817.stderr - testsuite/tests/rep-poly/T19615.stderr - testsuite/tests/rep-poly/T19709b.stderr - testsuite/tests/rep-poly/T21906.stderr - testsuite/tests/rep-poly/T23903.stderr - testsuite/tests/rep-poly/UnliftedNewtypesCoerceFail.stderr - testsuite/tests/typecheck/no_skolem_info/T14040.stderr - testsuite/tests/typecheck/should_compile/T25266a.stderr - testsuite/tests/typecheck/should_fail/T16204c.stderr - testsuite/tests/typecheck/should_fail/T7696.stderr - testsuite/tests/typecheck/should_fail/T8603.stderr The diff was not included because it is too large. View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/ac9fb269786a10221729731a4776c28… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/ac9fb269786a10221729731a4776c28… You're receiving this email because of your account on gitlab.haskell.org.
1 0
0 0
[Git][ghc/ghc][wip/romes/per-thread-step-in] debugger: Allow toggling step-in per thread
by Rodrigo Mesquita (@alt-romes) 20 May '25

20 May '25
Rodrigo Mesquita pushed to branch wip/romes/per-thread-step-in at Glasgow Haskell Compiler / GHC Commits: 49523b4b by Rodrigo Mesquita at 2025-05-20T13:49:00+01:00 debugger: Allow toggling step-in per thread The RTS global flag `rts_stop_next_breakpoint` globally sets the interpreter to stop at the immediate next breakpoint. With this commit, single step mode can additionally be set per thread in the TSO flag (TSO_STOP_NEXT_BREAKPOINT). Being able to toggle "stop at next breakpoint" per thread is an important requirement for implementing "stepping out" of a function in a multi-threaded context. And, more generally, having a per-thread flag for single-stepping paves the way for multi-threaded debugging. That said, when we want to enable "single step" mode for the whole interpreted program we still want to stop at the immediate next breakpoint, whichever thread it belongs to. That's why we also keep the global `rts_stop_next_breakpoint` flag, with `rts_enableStopNextBreakpointAll` and `rts_disableStopNextBreakpointAll` helpers. Preparation for #26042 - - - - - 9 changed files: - libraries/ghc-heap/GHC/Exts/Heap/Closures.hs - libraries/ghc-heap/GHC/Exts/Heap/FFIClosures_ProfilingDisabled.hsc - libraries/ghc-heap/GHC/Exts/Heap/FFIClosures_ProfilingEnabled.hsc - libraries/ghc-heap/tests/parse_tso_flags.hs - libraries/ghci/GHCi/Run.hs - rts/Interpreter.c - rts/Interpreter.h - rts/RtsSymbols.c - rts/include/rts/Constants.h Changes: ===================================== libraries/ghc-heap/GHC/Exts/Heap/Closures.hs ===================================== @@ -624,6 +624,7 @@ data TsoFlags | TsoMarked | TsoSqueezed | TsoAllocLimit + | TsoStopNextBreakpoint | TsoFlagsUnknownValue Word32 -- ^ Please report this as a bug deriving (Eq, Show, Generic, Ord) ===================================== libraries/ghc-heap/GHC/Exts/Heap/FFIClosures_ProfilingDisabled.hsc ===================================== @@ -87,6 +87,9 @@ parseTsoFlags w | isSet (#const TSO_LOCKED) w = TsoLocked : parseTsoFlags (unset | isSet (#const TSO_MARKED) w = TsoMarked : parseTsoFlags (unset (#const TSO_MARKED) w) | isSet (#const TSO_SQUEEZED) w = TsoSqueezed : parseTsoFlags (unset (#const TSO_SQUEEZED) w) | isSet (#const TSO_ALLOC_LIMIT) w = TsoAllocLimit : parseTsoFlags (unset (#const TSO_ALLOC_LIMIT) w) +#if __GLASGOW_HASKELL__ >= 913 + | isSet (#const TSO_STOP_NEXT_BREAKPOINT) w = TsoStopNextBreakpoint : parseTsoFlags (unset (#const TSO_STOP_NEXT_BREAKPOINT) w) +#endif parseTsoFlags 0 = [] parseTsoFlags w = [TsoFlagsUnknownValue w] ===================================== libraries/ghc-heap/GHC/Exts/Heap/FFIClosures_ProfilingEnabled.hsc ===================================== @@ -87,6 +87,9 @@ parseTsoFlags w | isSet (#const TSO_LOCKED) w = TsoLocked : parseTsoFlags (unset | isSet (#const TSO_MARKED) w = TsoMarked : parseTsoFlags (unset (#const TSO_MARKED) w) | isSet (#const TSO_SQUEEZED) w = TsoSqueezed : parseTsoFlags (unset (#const TSO_SQUEEZED) w) | isSet (#const TSO_ALLOC_LIMIT) w = TsoAllocLimit : parseTsoFlags (unset (#const TSO_ALLOC_LIMIT) w) +#if __GLASGOW_HASKELL__ >= 913 + | isSet (#const TSO_STOP_NEXT_BREAKPOINT) w = TsoStopNextBreakpoint : parseTsoFlags (unset (#const TSO_STOP_NEXT_BREAKPOINT) w) +#endif parseTsoFlags 0 = [] parseTsoFlags w = [TsoFlagsUnknownValue w] ===================================== libraries/ghc-heap/tests/parse_tso_flags.hs ===================================== @@ -13,5 +13,6 @@ main = do assertEqual (parseTsoFlags 64) [TsoMarked] assertEqual (parseTsoFlags 128) [TsoSqueezed] assertEqual (parseTsoFlags 256) [TsoAllocLimit] + assertEqual (parseTsoFlags 512) [TsoStopNextBreakpoint] assertEqual (parseTsoFlags 6) [TsoLocked, TsoBlockx] ===================================== libraries/ghci/GHCi/Run.hs ===================================== @@ -1,5 +1,5 @@ {-# LANGUAGE GADTs, RecordWildCards, MagicHash, ScopedTypeVariables, CPP, - UnboxedTuples, LambdaCase #-} + UnboxedTuples, LambdaCase, UnliftedFFITypes #-} {-# OPTIONS_GHC -fno-warn-name-shadowing #-} -- | @@ -396,13 +396,21 @@ abandonStmt hvref = do _ <- takeMVar resumeStatusMVar return () -foreign import ccall "&rts_stop_next_breakpoint" stepFlag :: Ptr CInt +foreign import ccall unsafe "rts_enableStopNextBreakpointAll" + rts_enableStopNextBreakpointAll :: IO () + +foreign import ccall unsafe "rts_disableStopNextBreakpointAll" + rts_disableStopNextBreakpointAll :: IO () + foreign import ccall "&rts_stop_on_exception" exceptionFlag :: Ptr CInt +-- | Enables the single step mode for all threads, thus stopping at any +-- existing breakpoint. setStepFlag :: IO () -setStepFlag = poke stepFlag 1 +setStepFlag = rts_enableStopNextBreakpointAll + resetStepFlag :: IO () -resetStepFlag = poke stepFlag 0 +resetStepFlag = rts_disableStopNextBreakpointAll type BreakpointCallback = Addr# -- pointer to the breakpoint tick module name ===================================== rts/Interpreter.c ===================================== @@ -243,9 +243,25 @@ allocate_NONUPD (Capability *cap, int n_words) return allocate(cap, stg_max(sizeofW(StgHeader)+MIN_PAYLOAD_SIZE, n_words)); } +// A global toggle for single-step mode. +// Unlike `TSO_STOP_NEXT_BREAKPOINT`, which sets single-step mode per-thread, +// `rts_stop_next_breakpoint` globally enables single-step mode. If enabled, we +// will stop at the immediate next breakpoint regardless of what thread it is in. int rts_stop_next_breakpoint = 0; int rts_stop_on_exception = 0; +// Enable the global single step mode +void rts_enableStopNextBreakpointAll() +{ + rts_stop_next_breakpoint = 1; +} + +// Disable the global single step mode +void rts_disableStopNextBreakpointAll() +{ + rts_stop_next_breakpoint = 0; +} + #if defined(INTERP_STATS) #define N_CODES 128 @@ -1250,7 +1266,7 @@ run_BCO: int arg8_cc; #endif StgArrBytes *breakPoints; - int returning_from_break; + int returning_from_break, stop_next_breakpoint; // the io action to run at a breakpoint StgClosure *ioAction; @@ -1280,6 +1296,13 @@ run_BCO: returning_from_break = cap->r.rCurrentTSO->flags & TSO_STOPPED_ON_BREAKPOINT; + // check whether this thread is set to stop at the immediate next + // breakpoint -- either by the global `rts_stop_next_breakpoint` + // flag, or by the local `TSO_STOP_NEXT_BREAKPOINT` + stop_next_breakpoint = + rts_stop_next_breakpoint || + cap->r.rCurrentTSO->flags & TSO_STOP_NEXT_BREAKPOINT; + #if defined(PROFILING) cap->r.rCCCS = pushCostCentre(cap->r.rCCCS, (CostCentre*)BCO_LIT(arg8_cc)); @@ -1291,20 +1314,20 @@ run_BCO: { breakPoints = (StgArrBytes *) BCO_PTR(arg1_brk_array); - // stop the current thread if either the - // "rts_stop_next_breakpoint" flag is true OR if the - // ignore count for this particular breakpoint is zero + // stop the current thread if either `stop_next_breakpoint` is + // true OR if the ignore count for this particular breakpoint is zero StgInt ignore_count = ((StgInt*)breakPoints->payload)[arg6_tick_index]; - if (rts_stop_next_breakpoint == false && ignore_count > 0) + if (stop_next_breakpoint == false && ignore_count > 0) { // decrement and write back ignore count ((StgInt*)breakPoints->payload)[arg6_tick_index] = --ignore_count; } - else if (rts_stop_next_breakpoint == true || ignore_count == 0) + else if (stop_next_breakpoint == true || ignore_count == 0) { // make sure we don't automatically stop at the // next breakpoint - rts_stop_next_breakpoint = false; + rts_stop_next_breakpoint = 0; + cap->r.rCurrentTSO->flags &= ~TSO_STOP_NEXT_BREAKPOINT; // allocate memory for a new AP_STACK, enough to // store the top stack frame plus an ===================================== rts/Interpreter.h ===================================== @@ -11,3 +11,6 @@ RTS_PRIVATE Capability *interpretBCO (Capability* cap); void interp_startup ( void ); void interp_shutdown ( void ); + +void rts_enableStopNextBreakpointAll (); +void rts_disableStopNextBreakpointAll (); ===================================== rts/RtsSymbols.c ===================================== @@ -906,7 +906,8 @@ extern char **environ; SymI_HasProto(revertCAFs) \ SymI_HasProto(RtsFlags) \ SymI_NeedsDataProto(rts_breakpoint_io_action) \ - SymI_NeedsDataProto(rts_stop_next_breakpoint) \ + SymI_NeedsDataProto(rts_enableStopNextBreakpointAll) \ + SymI_NeedsDataProto(rts_disableStopNextBreakpointAll) \ SymI_NeedsDataProto(rts_stop_on_exception) \ SymI_HasProto(stopTimer) \ SymI_HasProto(n_capabilities) \ ===================================== rts/include/rts/Constants.h ===================================== @@ -328,6 +328,12 @@ */ #define TSO_ALLOC_LIMIT 256 +/* + * Enables step-in mode for this thread -- it will stop at the immediate next + * breakpoint found in this thread. + */ +#define TSO_STOP_NEXT_BREAKPOINT 512 + /* * The number of times we spin in a spin lock before yielding (see * #3758). To tune this value, use the benchmark in #3758: run the View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/49523b4b98036dd317a8a8ddfa00ad4… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/49523b4b98036dd317a8a8ddfa00ad4… You're receiving this email because of your account on gitlab.haskell.org.
1 0
0 0
[Git][ghc/ghc][wip/andreask/interpreter_primops] 4 commits: Allow the 'data' keyword in import/export lists (#25899)
by Andreas Klebinger (@AndreasK) 20 May '25

20 May '25
Andreas Klebinger pushed to branch wip/andreask/interpreter_primops at Glasgow Haskell Compiler / GHC Commits: fd64667d by Vladislav Zavialov at 2025-05-20T03:25:08-04:00 Allow the 'data' keyword in import/export lists (#25899) This patch introduces the 'data' namespace specifier in import and export lists. The intended use is to import data constructors without their parent type constructors, e.g. import Data.Proxy as D (data Proxy) type DP = D.Proxy -- promoted data constructor Additionally, it is possible to use 'data' to explicitly qualify any data constructors or terms, incl. operators and field selectors import Prelude (Semigroup(data (<>))) import Data.Function (data (&)) import Data.Monoid (data Dual, data getDual) x = Dual "Hello" <> Dual "World" & getDual The implementation mostly builds on top of the existing logic for the 'type' and 'pattern' namespace specifiers, plus there are a few tweaks to how we generate suggestions in error messages. - - - - - acc86753 by Ben Gamari at 2025-05-20T03:25:51-04:00 compiler: Use field selectors when creating BCOs This makes it easier to grep for these fields. - - - - - 60a55fd7 by Ben Gamari at 2025-05-20T03:25:51-04:00 compiler: Clarify BCO size Previously the semantics and size of StgBCO was a bit unclear. Specifically, the `size` field was documented to contain the size of the bitmap whereas it was actually the size of the closure *and* bitmap. Additionally, it was not as clear as it could be that the bitmap was a full StgLargeBitmap with its own `size` field. - - - - - 8c50b15a by Andreas Klebinger at 2025-05-20T13:06:03+02:00 Interpreter: Add limited support for direct primop evaluation. This commit adds support for a number of primops directly to the interpreter. This avoids the indirection of going through the primop wrapper for those primops speeding interpretation of optimized code up massively. Code involving IntSet runs about 25% faster with optimized core and these changes. For core without breakpoints it's even more pronouced and I saw reductions in runtime by up to 50%. Running GHC itself in the interpreter was sped up by ~15% through this change. Additionally this comment does a few other related changes: testsuite: * Run foundation test in ghci and ghci-opt ways to test these primops. * Vastly expand the foundation test to cover all basic primops by comparing result with the result of calling the wrapper. Interpreter: * When pushing arguments for interpreted primops extend each argument to at least word with when pushing. This avoids some issues with big endian. We can revisit this if it causes performance issues. * Restructure the stack chunk check logic. There are now macros for read accesses which might cross stack chunk boundries and macros which omit the checks which are used when we statically know we access an address in the current stack chunk. - - - - - 59 changed files: - compiler/GHC/Builtin/primops.txt.pp - compiler/GHC/ByteCode/Asm.hs - compiler/GHC/ByteCode/Instr.hs - compiler/GHC/ByteCode/Linker.hs - compiler/GHC/Hs/ImpExp.hs - compiler/GHC/Iface/Ext/Ast.hs - compiler/GHC/Parser.y - compiler/GHC/Parser/PostProcess.hs - compiler/GHC/Rename/Names.hs - compiler/GHC/StgToByteCode.hs - compiler/GHC/Tc/Errors/Ppr.hs - compiler/GHC/Tc/Errors/Types.hs - compiler/GHC/Tc/Gen/Export.hs - compiler/GHC/Types/Error/Codes.hs - compiler/GHC/Types/Hint.hs - compiler/GHC/Types/Hint/Ppr.hs - compiler/Language/Haskell/Syntax/Extension.hs - compiler/Language/Haskell/Syntax/ImpExp.hs - docs/users_guide/9.14.1-notes.rst - docs/users_guide/exts/explicit_namespaces.rst - docs/users_guide/exts/pattern_synonyms.rst - rts/Disassembler.c - rts/Interpreter.c - rts/PrimOps.cmm - rts/include/rts/Bytecodes.h - rts/include/rts/storage/Closures.h - testsuite/tests/codeGen/should_run/all.T - + testsuite/tests/ghci/all.T - + testsuite/tests/ghci/ghci-mem-primops.hs - + testsuite/tests/ghci/ghci-mem-primops.script - + testsuite/tests/ghci/ghci-mem-primops.stdout - testsuite/tests/module/T21826.stderr - testsuite/tests/numeric/should_run/all.T - testsuite/tests/numeric/should_run/foundation.hs - testsuite/tests/numeric/should_run/foundation.stdout - testsuite/tests/rename/should_compile/T22581d.stdout - + testsuite/tests/rename/should_compile/T25899a.hs - + testsuite/tests/rename/should_compile/T25899b.hs - + testsuite/tests/rename/should_compile/T25899c.hs - + testsuite/tests/rename/should_compile/T25899c_helper.hs - + testsuite/tests/rename/should_compile/T25899d.script - + testsuite/tests/rename/should_compile/T25899d.stdout - testsuite/tests/rename/should_compile/all.T - testsuite/tests/rename/should_fail/T22581a.stderr - testsuite/tests/rename/should_fail/T22581b.stderr - + testsuite/tests/rename/should_fail/T25899e1.hs - + testsuite/tests/rename/should_fail/T25899e1.stderr - + testsuite/tests/rename/should_fail/T25899e2.hs - + testsuite/tests/rename/should_fail/T25899e2.stderr - + testsuite/tests/rename/should_fail/T25899e3.hs - + testsuite/tests/rename/should_fail/T25899e3.stderr - + testsuite/tests/rename/should_fail/T25899e_helper.hs - + testsuite/tests/rename/should_fail/T25899f.hs - + testsuite/tests/rename/should_fail/T25899f.stderr - + testsuite/tests/rename/should_fail/T25899f_helper.hs - testsuite/tests/rename/should_fail/all.T - utils/check-exact/ExactPrint.hs - utils/genprimopcode/Main.hs - utils/genprimopcode/Syntax.hs The diff was not included because it is too large. View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/1add43cb68ff6fe94067bcd7575996… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/1add43cb68ff6fe94067bcd7575996… You're receiving this email because of your account on gitlab.haskell.org.
1 0
0 0
[Git][ghc/ghc][wip/romes/per-thread-step-in] debugger: Allow toggling step-in per thread
by Rodrigo Mesquita (@alt-romes) 20 May '25

20 May '25
Rodrigo Mesquita pushed to branch wip/romes/per-thread-step-in at Glasgow Haskell Compiler / GHC Commits: 6bd338a8 by Rodrigo Mesquita at 2025-05-20T10:56:46+01:00 debugger: Allow toggling step-in per thread The RTS global flag `rts_stop_next_breakpoint` globally sets the interpreter to stop at the immediate next breakpoint. With this commit, single step mode can additionally be set per thread in the TSO flag (TSO_STOP_NEXT_BREAKPOINT). Being able to toggle "stop at next breakpoint" per thread is an important requirement for implementing "stepping out" of a function in a multi-threaded context. And, more generally, having a per-thread flag for single-stepping paves the way for multi-threaded debugging. That said, when we want to enable "single step" mode for the whole interpreted program we still want to stop at the immediate next breakpoint, whichever thread it belongs to. That's why we also keep the global `rts_stop_next_breakpoint` flag, with `rts_enableStopNextBreakpointAll` and `rts_disableStopNextBreakpointAll` helpers. Preparation for #26042 - - - - - 8 changed files: - libraries/ghc-heap/GHC/Exts/Heap/Closures.hs - libraries/ghc-heap/GHC/Exts/Heap/FFIClosures_ProfilingDisabled.hsc - libraries/ghc-heap/GHC/Exts/Heap/FFIClosures_ProfilingEnabled.hsc - libraries/ghc-heap/tests/parse_tso_flags.hs - libraries/ghci/GHCi/Run.hs - rts/Interpreter.c - rts/RtsSymbols.c - rts/include/rts/Constants.h Changes: ===================================== libraries/ghc-heap/GHC/Exts/Heap/Closures.hs ===================================== @@ -624,6 +624,7 @@ data TsoFlags | TsoMarked | TsoSqueezed | TsoAllocLimit + | TsoStopNextBreakpoint | TsoFlagsUnknownValue Word32 -- ^ Please report this as a bug deriving (Eq, Show, Generic, Ord) ===================================== libraries/ghc-heap/GHC/Exts/Heap/FFIClosures_ProfilingDisabled.hsc ===================================== @@ -87,6 +87,9 @@ parseTsoFlags w | isSet (#const TSO_LOCKED) w = TsoLocked : parseTsoFlags (unset | isSet (#const TSO_MARKED) w = TsoMarked : parseTsoFlags (unset (#const TSO_MARKED) w) | isSet (#const TSO_SQUEEZED) w = TsoSqueezed : parseTsoFlags (unset (#const TSO_SQUEEZED) w) | isSet (#const TSO_ALLOC_LIMIT) w = TsoAllocLimit : parseTsoFlags (unset (#const TSO_ALLOC_LIMIT) w) +#if __GLASGOW_HASKELL__ >= 913 + | isSet (#const TSO_STOP_NEXT_BREAKPOINT) w = TsoStopNextBreakpoint : parseTsoFlags (unset (#const TSO_STOP_NEXT_BREAKPOINT) w) +#endif parseTsoFlags 0 = [] parseTsoFlags w = [TsoFlagsUnknownValue w] ===================================== libraries/ghc-heap/GHC/Exts/Heap/FFIClosures_ProfilingEnabled.hsc ===================================== @@ -87,6 +87,9 @@ parseTsoFlags w | isSet (#const TSO_LOCKED) w = TsoLocked : parseTsoFlags (unset | isSet (#const TSO_MARKED) w = TsoMarked : parseTsoFlags (unset (#const TSO_MARKED) w) | isSet (#const TSO_SQUEEZED) w = TsoSqueezed : parseTsoFlags (unset (#const TSO_SQUEEZED) w) | isSet (#const TSO_ALLOC_LIMIT) w = TsoAllocLimit : parseTsoFlags (unset (#const TSO_ALLOC_LIMIT) w) +#if __GLASGOW_HASKELL__ >= 913 + | isSet (#const TSO_STOP_NEXT_BREAKPOINT) w = TsoStopNextBreakpoint : parseTsoFlags (unset (#const TSO_STOP_NEXT_BREAKPOINT) w) +#endif parseTsoFlags 0 = [] parseTsoFlags w = [TsoFlagsUnknownValue w] ===================================== libraries/ghc-heap/tests/parse_tso_flags.hs ===================================== @@ -13,5 +13,6 @@ main = do assertEqual (parseTsoFlags 64) [TsoMarked] assertEqual (parseTsoFlags 128) [TsoSqueezed] assertEqual (parseTsoFlags 256) [TsoAllocLimit] + assertEqual (parseTsoFlags 512) [TsoStopNextBreakpoint] assertEqual (parseTsoFlags 6) [TsoLocked, TsoBlockx] ===================================== libraries/ghci/GHCi/Run.hs ===================================== @@ -1,5 +1,5 @@ {-# LANGUAGE GADTs, RecordWildCards, MagicHash, ScopedTypeVariables, CPP, - UnboxedTuples, LambdaCase #-} + UnboxedTuples, LambdaCase, UnliftedFFITypes #-} {-# OPTIONS_GHC -fno-warn-name-shadowing #-} -- | @@ -396,13 +396,21 @@ abandonStmt hvref = do _ <- takeMVar resumeStatusMVar return () -foreign import ccall "&rts_stop_next_breakpoint" stepFlag :: Ptr CInt +foreign import ccall unsafe "rts_enableStopNextBreakpointAll" + rts_enableStopNextBreakpointAll :: IO () + +foreign import ccall unsafe "rts_disableStopNextBreakpointAll" + rts_disableStopNextBreakpointAll :: IO () + foreign import ccall "&rts_stop_on_exception" exceptionFlag :: Ptr CInt +-- | Enables the single step mode for all threads, thus stopping at any +-- existing breakpoint. setStepFlag :: IO () -setStepFlag = poke stepFlag 1 +setStepFlag = rts_enableStopNextBreakpointAll + resetStepFlag :: IO () -resetStepFlag = poke stepFlag 0 +resetStepFlag = rts_disableStopNextBreakpointAll type BreakpointCallback = Addr# -- pointer to the breakpoint tick module name ===================================== rts/Interpreter.c ===================================== @@ -243,9 +243,25 @@ allocate_NONUPD (Capability *cap, int n_words) return allocate(cap, stg_max(sizeofW(StgHeader)+MIN_PAYLOAD_SIZE, n_words)); } +// A global toggle for single-step mode. +// Unlike `TSO_STOP_NEXT_BREAKPOINT`, which sets single-step mode per-thread, +// `rts_stop_next_breakpoint` globally enables single-step mode. If enabled, we +// will stop at the immediate next breakpoint regardless of what thread it is in. int rts_stop_next_breakpoint = 0; int rts_stop_on_exception = 0; +// Enable the global single step mode +void rts_enableStopNextBreakpointAll() +{ + rts_stop_next_breakpoint = 1; +} + +// Disable the global single step mode +void rts_disableStopNextBreakpointAll() +{ + rts_stop_next_breakpoint = 0; +} + #if defined(INTERP_STATS) #define N_CODES 128 @@ -1250,7 +1266,7 @@ run_BCO: int arg8_cc; #endif StgArrBytes *breakPoints; - int returning_from_break; + int returning_from_break, stop_next_breakpoint; // the io action to run at a breakpoint StgClosure *ioAction; @@ -1280,6 +1296,13 @@ run_BCO: returning_from_break = cap->r.rCurrentTSO->flags & TSO_STOPPED_ON_BREAKPOINT; + // check whether this thread is set to stop at the immediate next + // breakpoint -- either by the global `rts_stop_next_breakpoint` + // flag, or by the local `TSO_STOP_NEXT_BREAKPOINT` + stop_next_breakpoint = + rts_stop_next_breakpoint || + cap->r.rCurrentTSO->flags & TSO_STOP_NEXT_BREAKPOINT; + #if defined(PROFILING) cap->r.rCCCS = pushCostCentre(cap->r.rCCCS, (CostCentre*)BCO_LIT(arg8_cc)); @@ -1290,21 +1313,22 @@ run_BCO: if (!returning_from_break) { breakPoints = (StgArrBytes *) BCO_PTR(arg1_brk_array); + - // stop the current thread if either the - // "rts_stop_next_breakpoint" flag is true OR if the - // ignore count for this particular breakpoint is zero + // stop the current thread if either `stop_next_breakpoint` is + // true OR if the ignore count for this particular breakpoint is zero StgInt ignore_count = ((StgInt*)breakPoints->payload)[arg6_tick_index]; - if (rts_stop_next_breakpoint == false && ignore_count > 0) + if (stop_next_breakpoint == false && ignore_count > 0) { // decrement and write back ignore count ((StgInt*)breakPoints->payload)[arg6_tick_index] = --ignore_count; } - else if (rts_stop_next_breakpoint == true || ignore_count == 0) + else if (stop_next_breakpoint == true || ignore_count == 0) { // make sure we don't automatically stop at the // next breakpoint - rts_stop_next_breakpoint = false; + rts_stop_next_breakpoint = 0; + cap->r.rCurrentTSO->flags &= ~TSO_STOP_NEXT_BREAKPOINT; // allocate memory for a new AP_STACK, enough to // store the top stack frame plus an ===================================== rts/RtsSymbols.c ===================================== @@ -906,7 +906,8 @@ extern char **environ; SymI_HasProto(revertCAFs) \ SymI_HasProto(RtsFlags) \ SymI_NeedsDataProto(rts_breakpoint_io_action) \ - SymI_NeedsDataProto(rts_stop_next_breakpoint) \ + SymI_NeedsDataProto(rts_enableStopNextBreakpointAll) \ + SymI_NeedsDataProto(rts_disableStopNextBreakpointAll) \ SymI_NeedsDataProto(rts_stop_on_exception) \ SymI_HasProto(stopTimer) \ SymI_HasProto(n_capabilities) \ ===================================== rts/include/rts/Constants.h ===================================== @@ -328,6 +328,12 @@ */ #define TSO_ALLOC_LIMIT 256 +/* + * Enables step-in mode for this thread -- it will stop at the immediate next + * breakpoint found in this thread. + */ +#define TSO_STOP_NEXT_BREAKPOINT 512 + /* * The number of times we spin in a spin lock before yielding (see * #3758). To tune this value, use the benchmark in #3758: run the View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/6bd338a8f2db7b280c8cdf4b3bc2a04… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/6bd338a8f2db7b280c8cdf4b3bc2a04… You're receiving this email because of your account on gitlab.haskell.org.
1 0
0 0
[Git][ghc/ghc][wip/romes/per-thread-step-in] debugger: Toggle step-in per thread, not globally
by Rodrigo Mesquita (@alt-romes) 20 May '25

20 May '25
Rodrigo Mesquita pushed to branch wip/romes/per-thread-step-in at Glasgow Haskell Compiler / GHC Commits: 5bbf076c by Rodrigo Mesquita at 2025-05-20T10:55:56+01:00 debugger: Toggle step-in per thread, not globally The RTS global flag `rts_stop_next_breakpoint` used to tell the interpreter to stop at the immediate next breakpoint. Now, this flag is definited per thread in the TSO flag (TSO_STOP_NEXT_BREAKPOINT). Being able to toggle "stop at next breakpoint" per thread is an important requirement for implementing "stepping out" of a function in a multi-threaded context. More generally, having a per-thread flag for single-stepping paves the way for multi-threaded debugging. That said, when we want to enable "single step" mode for the whole interpreted program we still want to stop at the immediate next breakpoint, whichever thread it belongs to. Therefore, use `rts_enableStopNextBreakpointAll` and `rts_disableStopNextBreakpointAll` for the exisiting single-step commands. Preparation for #26042 - - - - - 8 changed files: - libraries/ghc-heap/GHC/Exts/Heap/Closures.hs - libraries/ghc-heap/GHC/Exts/Heap/FFIClosures_ProfilingDisabled.hsc - libraries/ghc-heap/GHC/Exts/Heap/FFIClosures_ProfilingEnabled.hsc - libraries/ghc-heap/tests/parse_tso_flags.hs - libraries/ghci/GHCi/Run.hs - rts/Interpreter.c - rts/RtsSymbols.c - rts/include/rts/Constants.h Changes: ===================================== libraries/ghc-heap/GHC/Exts/Heap/Closures.hs ===================================== @@ -624,6 +624,7 @@ data TsoFlags | TsoMarked | TsoSqueezed | TsoAllocLimit + | TsoStopNextBreakpoint | TsoFlagsUnknownValue Word32 -- ^ Please report this as a bug deriving (Eq, Show, Generic, Ord) ===================================== libraries/ghc-heap/GHC/Exts/Heap/FFIClosures_ProfilingDisabled.hsc ===================================== @@ -87,6 +87,9 @@ parseTsoFlags w | isSet (#const TSO_LOCKED) w = TsoLocked : parseTsoFlags (unset | isSet (#const TSO_MARKED) w = TsoMarked : parseTsoFlags (unset (#const TSO_MARKED) w) | isSet (#const TSO_SQUEEZED) w = TsoSqueezed : parseTsoFlags (unset (#const TSO_SQUEEZED) w) | isSet (#const TSO_ALLOC_LIMIT) w = TsoAllocLimit : parseTsoFlags (unset (#const TSO_ALLOC_LIMIT) w) +#if __GLASGOW_HASKELL__ >= 913 + | isSet (#const TSO_STOP_NEXT_BREAKPOINT) w = TsoStopNextBreakpoint : parseTsoFlags (unset (#const TSO_STOP_NEXT_BREAKPOINT) w) +#endif parseTsoFlags 0 = [] parseTsoFlags w = [TsoFlagsUnknownValue w] ===================================== libraries/ghc-heap/GHC/Exts/Heap/FFIClosures_ProfilingEnabled.hsc ===================================== @@ -87,6 +87,9 @@ parseTsoFlags w | isSet (#const TSO_LOCKED) w = TsoLocked : parseTsoFlags (unset | isSet (#const TSO_MARKED) w = TsoMarked : parseTsoFlags (unset (#const TSO_MARKED) w) | isSet (#const TSO_SQUEEZED) w = TsoSqueezed : parseTsoFlags (unset (#const TSO_SQUEEZED) w) | isSet (#const TSO_ALLOC_LIMIT) w = TsoAllocLimit : parseTsoFlags (unset (#const TSO_ALLOC_LIMIT) w) +#if __GLASGOW_HASKELL__ >= 913 + | isSet (#const TSO_STOP_NEXT_BREAKPOINT) w = TsoStopNextBreakpoint : parseTsoFlags (unset (#const TSO_STOP_NEXT_BREAKPOINT) w) +#endif parseTsoFlags 0 = [] parseTsoFlags w = [TsoFlagsUnknownValue w] ===================================== libraries/ghc-heap/tests/parse_tso_flags.hs ===================================== @@ -13,5 +13,6 @@ main = do assertEqual (parseTsoFlags 64) [TsoMarked] assertEqual (parseTsoFlags 128) [TsoSqueezed] assertEqual (parseTsoFlags 256) [TsoAllocLimit] + assertEqual (parseTsoFlags 512) [TsoStopNextBreakpoint] assertEqual (parseTsoFlags 6) [TsoLocked, TsoBlockx] ===================================== libraries/ghci/GHCi/Run.hs ===================================== @@ -1,5 +1,5 @@ {-# LANGUAGE GADTs, RecordWildCards, MagicHash, ScopedTypeVariables, CPP, - UnboxedTuples, LambdaCase #-} + UnboxedTuples, LambdaCase, UnliftedFFITypes #-} {-# OPTIONS_GHC -fno-warn-name-shadowing #-} -- | @@ -396,13 +396,21 @@ abandonStmt hvref = do _ <- takeMVar resumeStatusMVar return () -foreign import ccall "&rts_stop_next_breakpoint" stepFlag :: Ptr CInt +foreign import ccall unsafe "rts_enableStopNextBreakpointAll" + rts_enableStopNextBreakpointAll :: IO () + +foreign import ccall unsafe "rts_disableStopNextBreakpointAll" + rts_disableStopNextBreakpointAll :: IO () + foreign import ccall "&rts_stop_on_exception" exceptionFlag :: Ptr CInt +-- | Enables the single step mode for all threads, thus stopping at any +-- existing breakpoint. setStepFlag :: IO () -setStepFlag = poke stepFlag 1 +setStepFlag = rts_enableStopNextBreakpointAll + resetStepFlag :: IO () -resetStepFlag = poke stepFlag 0 +resetStepFlag = rts_disableStopNextBreakpointAll type BreakpointCallback = Addr# -- pointer to the breakpoint tick module name ===================================== rts/Interpreter.c ===================================== @@ -243,9 +243,25 @@ allocate_NONUPD (Capability *cap, int n_words) return allocate(cap, stg_max(sizeofW(StgHeader)+MIN_PAYLOAD_SIZE, n_words)); } +// A global toggle for single-step mode. +// Unlike `TSO_STOP_NEXT_BREAKPOINT`, which sets single-step mode per-thread, +// `rts_stop_next_breakpoint` globally enables single-step mode. If enabled, we +// will stop at the immediate next breakpoint regardless of what thread it is in. int rts_stop_next_breakpoint = 0; int rts_stop_on_exception = 0; +// Enable the global single step mode +void rts_enableStopNextBreakpointAll() +{ + rts_stop_next_breakpoint = 1; +} + +// Disable the global single step mode +void rts_disableStopNextBreakpointAll() +{ + rts_stop_next_breakpoint = 0; +} + #if defined(INTERP_STATS) #define N_CODES 128 @@ -1250,7 +1266,7 @@ run_BCO: int arg8_cc; #endif StgArrBytes *breakPoints; - int returning_from_break; + int returning_from_break, stop_next_breakpoint; // the io action to run at a breakpoint StgClosure *ioAction; @@ -1280,6 +1296,13 @@ run_BCO: returning_from_break = cap->r.rCurrentTSO->flags & TSO_STOPPED_ON_BREAKPOINT; + // check whether this thread is set to stop at the immediate next + // breakpoint -- either by the global `rts_stop_next_breakpoint` + // flag, or by the local `TSO_STOP_NEXT_BREAKPOINT` + stop_next_breakpoint = + rts_stop_next_breakpoint || + cap->r.rCurrentTSO->flags & TSO_STOP_NEXT_BREAKPOINT; + #if defined(PROFILING) cap->r.rCCCS = pushCostCentre(cap->r.rCCCS, (CostCentre*)BCO_LIT(arg8_cc)); @@ -1290,21 +1313,22 @@ run_BCO: if (!returning_from_break) { breakPoints = (StgArrBytes *) BCO_PTR(arg1_brk_array); + - // stop the current thread if either the - // "rts_stop_next_breakpoint" flag is true OR if the - // ignore count for this particular breakpoint is zero + // stop the current thread if either `stop_next_breakpoint` is + // true OR if the ignore count for this particular breakpoint is zero StgInt ignore_count = ((StgInt*)breakPoints->payload)[arg6_tick_index]; - if (rts_stop_next_breakpoint == false && ignore_count > 0) + if (stop_next_breakpoint == false && ignore_count > 0) { // decrement and write back ignore count ((StgInt*)breakPoints->payload)[arg6_tick_index] = --ignore_count; } - else if (rts_stop_next_breakpoint == true || ignore_count == 0) + else if (stop_next_breakpoint == true || ignore_count == 0) { // make sure we don't automatically stop at the // next breakpoint - rts_stop_next_breakpoint = false; + rts_stop_next_breakpoint = 0; + cap->r.rCurrentTSO->flags &= ~TSO_STOP_NEXT_BREAKPOINT; // allocate memory for a new AP_STACK, enough to // store the top stack frame plus an ===================================== rts/RtsSymbols.c ===================================== @@ -906,7 +906,8 @@ extern char **environ; SymI_HasProto(revertCAFs) \ SymI_HasProto(RtsFlags) \ SymI_NeedsDataProto(rts_breakpoint_io_action) \ - SymI_NeedsDataProto(rts_stop_next_breakpoint) \ + SymI_NeedsDataProto(rts_enableStopNextBreakpointAll) \ + SymI_NeedsDataProto(rts_disableStopNextBreakpointAll) \ SymI_NeedsDataProto(rts_stop_on_exception) \ SymI_HasProto(stopTimer) \ SymI_HasProto(n_capabilities) \ ===================================== rts/include/rts/Constants.h ===================================== @@ -328,6 +328,12 @@ */ #define TSO_ALLOC_LIMIT 256 +/* + * Enables step-in mode for this thread -- it will stop at the immediate next + * breakpoint found in this thread. + */ +#define TSO_STOP_NEXT_BREAKPOINT 512 + /* * The number of times we spin in a spin lock before yielding (see * #3758). To tune this value, use the benchmark in #3758: run the View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/5bbf076cdb726fb3534c394b699bd3a… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/5bbf076cdb726fb3534c394b699bd3a… You're receiving this email because of your account on gitlab.haskell.org.
1 0
0 0
[Git][ghc/ghc][wip/romes/per-thread-step-in] debugger: Toggle step-in per thread, not globally
by Rodrigo Mesquita (@alt-romes) 20 May '25

20 May '25
Rodrigo Mesquita pushed to branch wip/romes/per-thread-step-in at Glasgow Haskell Compiler / GHC Commits: 22d38925 by Rodrigo Mesquita at 2025-05-20T10:48:03+01:00 debugger: Toggle step-in per thread, not globally The RTS global flag `rts_stop_next_breakpoint` used to tell the interpreter to stop at the immediate next breakpoint. Now, this flag is definited per thread in the TSO flag (TSO_STOP_NEXT_BREAKPOINT). Being able to toggle "stop at next breakpoint" per thread is an important requirement for implementing "stepping out" of a function in a multi-threaded context. More generally, having a per-thread flag for single-stepping paves the way for multi-threaded debugging. That said, when we want to enable "single step" mode for the whole interpreted program we still want to stop at the immediate next breakpoint, whichever thread it belongs to. Therefore, use `rts_enableStopNextBreakpointAll` and `rts_disableStopNextBreakpointAll` for the exisiting single-step commands. Preparation for #26042 - - - - - 8 changed files: - libraries/ghc-heap/GHC/Exts/Heap/Closures.hs - libraries/ghc-heap/GHC/Exts/Heap/FFIClosures_ProfilingDisabled.hsc - libraries/ghc-heap/GHC/Exts/Heap/FFIClosures_ProfilingEnabled.hsc - libraries/ghc-heap/tests/parse_tso_flags.hs - libraries/ghci/GHCi/Run.hs - rts/Interpreter.c - rts/RtsSymbols.c - rts/include/rts/Constants.h Changes: ===================================== libraries/ghc-heap/GHC/Exts/Heap/Closures.hs ===================================== @@ -624,6 +624,7 @@ data TsoFlags | TsoMarked | TsoSqueezed | TsoAllocLimit + | TsoStopNextBreakpoint | TsoFlagsUnknownValue Word32 -- ^ Please report this as a bug deriving (Eq, Show, Generic, Ord) ===================================== libraries/ghc-heap/GHC/Exts/Heap/FFIClosures_ProfilingDisabled.hsc ===================================== @@ -87,6 +87,9 @@ parseTsoFlags w | isSet (#const TSO_LOCKED) w = TsoLocked : parseTsoFlags (unset | isSet (#const TSO_MARKED) w = TsoMarked : parseTsoFlags (unset (#const TSO_MARKED) w) | isSet (#const TSO_SQUEEZED) w = TsoSqueezed : parseTsoFlags (unset (#const TSO_SQUEEZED) w) | isSet (#const TSO_ALLOC_LIMIT) w = TsoAllocLimit : parseTsoFlags (unset (#const TSO_ALLOC_LIMIT) w) +#if __GLASGOW_HASKELL__ >= 913 + | isSet (#const TSO_STOP_NEXT_BREAKPOINT) w = TsoStopNextBreakpoint : parseTsoFlags (unset (#const TSO_STOP_NEXT_BREAKPOINT) w) +#endif parseTsoFlags 0 = [] parseTsoFlags w = [TsoFlagsUnknownValue w] ===================================== libraries/ghc-heap/GHC/Exts/Heap/FFIClosures_ProfilingEnabled.hsc ===================================== @@ -87,6 +87,9 @@ parseTsoFlags w | isSet (#const TSO_LOCKED) w = TsoLocked : parseTsoFlags (unset | isSet (#const TSO_MARKED) w = TsoMarked : parseTsoFlags (unset (#const TSO_MARKED) w) | isSet (#const TSO_SQUEEZED) w = TsoSqueezed : parseTsoFlags (unset (#const TSO_SQUEEZED) w) | isSet (#const TSO_ALLOC_LIMIT) w = TsoAllocLimit : parseTsoFlags (unset (#const TSO_ALLOC_LIMIT) w) +#if __GLASGOW_HASKELL__ >= 913 + | isSet (#const TSO_STOP_NEXT_BREAKPOINT) w = TsoStopNextBreakpoint : parseTsoFlags (unset (#const TSO_STOP_NEXT_BREAKPOINT) w) +#endif parseTsoFlags 0 = [] parseTsoFlags w = [TsoFlagsUnknownValue w] ===================================== libraries/ghc-heap/tests/parse_tso_flags.hs ===================================== @@ -13,5 +13,6 @@ main = do assertEqual (parseTsoFlags 64) [TsoMarked] assertEqual (parseTsoFlags 128) [TsoSqueezed] assertEqual (parseTsoFlags 256) [TsoAllocLimit] + assertEqual (parseTsoFlags 512) [TsoStopNextBreakpoint] assertEqual (parseTsoFlags 6) [TsoLocked, TsoBlockx] ===================================== libraries/ghci/GHCi/Run.hs ===================================== @@ -1,5 +1,5 @@ {-# LANGUAGE GADTs, RecordWildCards, MagicHash, ScopedTypeVariables, CPP, - UnboxedTuples, LambdaCase #-} + UnboxedTuples, LambdaCase, UnliftedFFITypes #-} {-# OPTIONS_GHC -fno-warn-name-shadowing #-} -- | @@ -396,13 +396,21 @@ abandonStmt hvref = do _ <- takeMVar resumeStatusMVar return () -foreign import ccall "&rts_stop_next_breakpoint" stepFlag :: Ptr CInt +foreign import ccall unsafe "rts_enableStopNextBreakpointAll" + rts_enableStopNextBreakpointAll :: IO () + +foreign import ccall unsafe "rts_disableStopNextBreakpointAll" + rts_disableStopNextBreakpointAll :: IO () + foreign import ccall "&rts_stop_on_exception" exceptionFlag :: Ptr CInt +-- | Enables the single step mode for all threads, thus stopping at any +-- existing breakpoint. setStepFlag :: IO () -setStepFlag = poke stepFlag 1 +setStepFlag = rts_enableStopNextBreakpointAll + resetStepFlag :: IO () -resetStepFlag = poke stepFlag 0 +resetStepFlag = rts_disableStopNextBreakpointAll type BreakpointCallback = Addr# -- pointer to the breakpoint tick module name ===================================== rts/Interpreter.c ===================================== @@ -243,9 +243,25 @@ allocate_NONUPD (Capability *cap, int n_words) return allocate(cap, stg_max(sizeofW(StgHeader)+MIN_PAYLOAD_SIZE, n_words)); } +// A global toggle for single-step mode. +// Unlike `TSO_STOP_NEXT_BREAKPOINT`, which sets single-step mode per-thread, +// `rts_stop_next_breakpoint` globally enables single-step mode. If enabled, we +// will stop at the immediate next breakpoint regardless of what thread it is in. int rts_stop_next_breakpoint = 0; int rts_stop_on_exception = 0; +// Enable "TSO_STOP_NEXT_BREAKPOINT" on all TSOs +void rts_enableStopNextBreakpointAll() +{ + rts_stop_next_breakpoint = 1; +} + +// Disable "TSO_STOP_NEXT_BREAKPOINT" on all TSOs +void rts_disableStopNextBreakpointAll() +{ + rts_stop_next_breakpoint = 0; +} + #if defined(INTERP_STATS) #define N_CODES 128 @@ -1250,7 +1266,7 @@ run_BCO: int arg8_cc; #endif StgArrBytes *breakPoints; - int returning_from_break; + int returning_from_break, stop_next_breakpoint; // the io action to run at a breakpoint StgClosure *ioAction; @@ -1280,6 +1296,13 @@ run_BCO: returning_from_break = cap->r.rCurrentTSO->flags & TSO_STOPPED_ON_BREAKPOINT; + // check whether this thread is set to stop at the immediate next + // breakpoint -- either by the global `rts_stop_next_breakpoint` + // flag, or by the local `TSO_STOP_NEXT_BREAKPOINT` + stop_next_breakpoint = + rts_stop_next_breakpoint || + cap->r.rCurrentTSO->flags & TSO_STOP_NEXT_BREAKPOINT; + #if defined(PROFILING) cap->r.rCCCS = pushCostCentre(cap->r.rCCCS, (CostCentre*)BCO_LIT(arg8_cc)); @@ -1290,21 +1313,23 @@ run_BCO: if (!returning_from_break) { breakPoints = (StgArrBytes *) BCO_PTR(arg1_brk_array); + // stop the current thread if either the - // "rts_stop_next_breakpoint" flag is true OR if the + // "TSO_STOP_NEXT_BREAKPOINT" flag is true OR if the // ignore count for this particular breakpoint is zero StgInt ignore_count = ((StgInt*)breakPoints->payload)[arg6_tick_index]; - if (rts_stop_next_breakpoint == false && ignore_count > 0) + if (stop_next_breakpoint == false && ignore_count > 0) { // decrement and write back ignore count ((StgInt*)breakPoints->payload)[arg6_tick_index] = --ignore_count; } - else if (rts_stop_next_breakpoint == true || ignore_count == 0) + else if (stop_next_breakpoint == true || ignore_count == 0) { // make sure we don't automatically stop at the // next breakpoint - rts_stop_next_breakpoint = false; + rts_stop_next_breakpoint = 0; + cap->r.rCurrentTSO->flags &= ~TSO_STOP_NEXT_BREAKPOINT; // allocate memory for a new AP_STACK, enough to // store the top stack frame plus an ===================================== rts/RtsSymbols.c ===================================== @@ -906,7 +906,8 @@ extern char **environ; SymI_HasProto(revertCAFs) \ SymI_HasProto(RtsFlags) \ SymI_NeedsDataProto(rts_breakpoint_io_action) \ - SymI_NeedsDataProto(rts_stop_next_breakpoint) \ + SymI_NeedsDataProto(rts_enableStopNextBreakpointAll) \ + SymI_NeedsDataProto(rts_disableStopNextBreakpointAll) \ SymI_NeedsDataProto(rts_stop_on_exception) \ SymI_HasProto(stopTimer) \ SymI_HasProto(n_capabilities) \ ===================================== rts/include/rts/Constants.h ===================================== @@ -328,6 +328,12 @@ */ #define TSO_ALLOC_LIMIT 256 +/* + * Enables step-in mode for this thread -- it will stop at the immediate next + * breakpoint found in this thread. + */ +#define TSO_STOP_NEXT_BREAKPOINT 512 + /* * The number of times we spin in a spin lock before yielding (see * #3758). To tune this value, use the benchmark in #3758: run the View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/22d3892511f7d39ee26b9439d97c7e5… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/22d3892511f7d39ee26b9439d97c7e5… You're receiving this email because of your account on gitlab.haskell.org.
1 0
0 0
[Git][ghc/ghc][wip/romes/per-thread-step-in] debugger: Toggle step-in per thread, not globally
by Rodrigo Mesquita (@alt-romes) 20 May '25

20 May '25
Rodrigo Mesquita pushed to branch wip/romes/per-thread-step-in at Glasgow Haskell Compiler / GHC Commits: 9ffc8223 by Rodrigo Mesquita at 2025-05-20T10:35:49+01:00 debugger: Toggle step-in per thread, not globally The RTS global flag `rts_stop_next_breakpoint` used to tell the interpreter to stop at the immediate next breakpoint. Now, this flag is definited per thread in the TSO flag (TSO_STOP_NEXT_BREAKPOINT). Being able to toggle "stop at next breakpoint" per thread is an important requirement for implementing "stepping out" of a function in a multi-threaded context. More generally, having a per-thread flag for single-stepping paves the way for multi-threaded debugging. That said, when we want to enable "single step" mode for the whole interpreted program we still want to stop at the immediate next breakpoint, whichever thread it belongs to. Therefore, use `rts_enableStopNextBreakpointAll` and `rts_disableStopNextBreakpointAll` for the exisiting single-step commands. Preparation for #26042 - - - - - 7 changed files: - libraries/ghc-heap/GHC/Exts/Heap/Closures.hs - libraries/ghc-heap/GHC/Exts/Heap/FFIClosures_ProfilingDisabled.hsc - libraries/ghc-heap/GHC/Exts/Heap/FFIClosures_ProfilingEnabled.hsc - libraries/ghci/GHCi/Run.hs - rts/Interpreter.c - rts/RtsSymbols.c - rts/include/rts/Constants.h Changes: ===================================== libraries/ghc-heap/GHC/Exts/Heap/Closures.hs ===================================== @@ -624,6 +624,7 @@ data TsoFlags | TsoMarked | TsoSqueezed | TsoAllocLimit + | TsoStopNextBreakpoint | TsoFlagsUnknownValue Word32 -- ^ Please report this as a bug deriving (Eq, Show, Generic, Ord) ===================================== libraries/ghc-heap/GHC/Exts/Heap/FFIClosures_ProfilingDisabled.hsc ===================================== @@ -87,6 +87,9 @@ parseTsoFlags w | isSet (#const TSO_LOCKED) w = TsoLocked : parseTsoFlags (unset | isSet (#const TSO_MARKED) w = TsoMarked : parseTsoFlags (unset (#const TSO_MARKED) w) | isSet (#const TSO_SQUEEZED) w = TsoSqueezed : parseTsoFlags (unset (#const TSO_SQUEEZED) w) | isSet (#const TSO_ALLOC_LIMIT) w = TsoAllocLimit : parseTsoFlags (unset (#const TSO_ALLOC_LIMIT) w) +#if __GLASGOW_HASKELL__ >= 913 + | isSet (#const TSO_STOP_NEXT_BREAKPOINT) w = TsoStopNextBreakpoint : parseTsoFlags (unset (#const TSO_STOP_NEXT_BREAKPOINT) w) +#endif parseTsoFlags 0 = [] parseTsoFlags w = [TsoFlagsUnknownValue w] ===================================== libraries/ghc-heap/GHC/Exts/Heap/FFIClosures_ProfilingEnabled.hsc ===================================== @@ -87,6 +87,9 @@ parseTsoFlags w | isSet (#const TSO_LOCKED) w = TsoLocked : parseTsoFlags (unset | isSet (#const TSO_MARKED) w = TsoMarked : parseTsoFlags (unset (#const TSO_MARKED) w) | isSet (#const TSO_SQUEEZED) w = TsoSqueezed : parseTsoFlags (unset (#const TSO_SQUEEZED) w) | isSet (#const TSO_ALLOC_LIMIT) w = TsoAllocLimit : parseTsoFlags (unset (#const TSO_ALLOC_LIMIT) w) +#if __GLASGOW_HASKELL__ >= 913 + | isSet (#const TSO_STOP_NEXT_BREAKPOINT) w = TsoStopNextBreakpoint : parseTsoFlags (unset (#const TSO_STOP_NEXT_BREAKPOINT) w) +#endif parseTsoFlags 0 = [] parseTsoFlags w = [TsoFlagsUnknownValue w] ===================================== libraries/ghci/GHCi/Run.hs ===================================== @@ -1,5 +1,5 @@ {-# LANGUAGE GADTs, RecordWildCards, MagicHash, ScopedTypeVariables, CPP, - UnboxedTuples, LambdaCase #-} + UnboxedTuples, LambdaCase, UnliftedFFITypes #-} {-# OPTIONS_GHC -fno-warn-name-shadowing #-} -- | @@ -396,13 +396,21 @@ abandonStmt hvref = do _ <- takeMVar resumeStatusMVar return () -foreign import ccall "&rts_stop_next_breakpoint" stepFlag :: Ptr CInt +foreign import ccall unsafe "rts_enableStopNextBreakpointAll" + rts_enableStopNextBreakpointAll :: IO () + +foreign import ccall unsafe "rts_disableStopNextBreakpointAll" + rts_disableStopNextBreakpointAll :: IO () + foreign import ccall "&rts_stop_on_exception" exceptionFlag :: Ptr CInt +-- | Enables the single step mode for all threads, thus stopping at any +-- existing breakpoint. setStepFlag :: IO () -setStepFlag = poke stepFlag 1 +setStepFlag = rts_enableStopNextBreakpointAll + resetStepFlag :: IO () -resetStepFlag = poke stepFlag 0 +resetStepFlag = rts_disableStopNextBreakpointAll type BreakpointCallback = Addr# -- pointer to the breakpoint tick module name ===================================== rts/Interpreter.c ===================================== @@ -243,9 +243,25 @@ allocate_NONUPD (Capability *cap, int n_words) return allocate(cap, stg_max(sizeofW(StgHeader)+MIN_PAYLOAD_SIZE, n_words)); } +// A global toggle for single-step mode. +// Unlike `TSO_STOP_NEXT_BREAKPOINT`, which sets single-step mode per-thread, +// `rts_stop_next_breakpoint` globally enables single-step mode. If enabled, we +// will stop at the immediate next breakpoint regardless of what thread it is in. int rts_stop_next_breakpoint = 0; int rts_stop_on_exception = 0; +// Enable "TSO_STOP_NEXT_BREAKPOINT" on all TSOs +void rts_enableStopNextBreakpointAll() +{ + rts_stop_next_breakpoint = 1; +} + +// Disable "TSO_STOP_NEXT_BREAKPOINT" on all TSOs +void rts_disableStopNextBreakpointAll() +{ + rts_stop_next_breakpoint = 0; +} + #if defined(INTERP_STATS) #define N_CODES 128 @@ -1250,7 +1266,7 @@ run_BCO: int arg8_cc; #endif StgArrBytes *breakPoints; - int returning_from_break; + int returning_from_break, stop_next_breakpoint; // the io action to run at a breakpoint StgClosure *ioAction; @@ -1280,6 +1296,13 @@ run_BCO: returning_from_break = cap->r.rCurrentTSO->flags & TSO_STOPPED_ON_BREAKPOINT; + // check whether this thread is set to stop at the immediate next + // breakpoint -- either by the global `rts_stop_next_breakpoint` + // flag, or by the local `TSO_STOP_NEXT_BREAKPOINT` + stop_next_breakpoint = + rts_stop_next_breakpoint || + cap->r.rCurrentTSO->flags & TSO_STOP_NEXT_BREAKPOINT; + #if defined(PROFILING) cap->r.rCCCS = pushCostCentre(cap->r.rCCCS, (CostCentre*)BCO_LIT(arg8_cc)); @@ -1290,21 +1313,23 @@ run_BCO: if (!returning_from_break) { breakPoints = (StgArrBytes *) BCO_PTR(arg1_brk_array); + // stop the current thread if either the - // "rts_stop_next_breakpoint" flag is true OR if the + // "TSO_STOP_NEXT_BREAKPOINT" flag is true OR if the // ignore count for this particular breakpoint is zero StgInt ignore_count = ((StgInt*)breakPoints->payload)[arg6_tick_index]; - if (rts_stop_next_breakpoint == false && ignore_count > 0) + if (stop_next_breakpoint == false && ignore_count > 0) { // decrement and write back ignore count ((StgInt*)breakPoints->payload)[arg6_tick_index] = --ignore_count; } - else if (rts_stop_next_breakpoint == true || ignore_count == 0) + else if (stop_next_breakpoint == true || ignore_count == 0) { // make sure we don't automatically stop at the // next breakpoint - rts_stop_next_breakpoint = false; + rts_stop_next_breakpoint = 0; + cap->r.rCurrentTSO->flags &= ~TSO_STOP_NEXT_BREAKPOINT; // allocate memory for a new AP_STACK, enough to // store the top stack frame plus an ===================================== rts/RtsSymbols.c ===================================== @@ -906,7 +906,8 @@ extern char **environ; SymI_HasProto(revertCAFs) \ SymI_HasProto(RtsFlags) \ SymI_NeedsDataProto(rts_breakpoint_io_action) \ - SymI_NeedsDataProto(rts_stop_next_breakpoint) \ + SymI_NeedsDataProto(rts_enableStopNextBreakpointAll) \ + SymI_NeedsDataProto(rts_disableStopNextBreakpointAll) \ SymI_NeedsDataProto(rts_stop_on_exception) \ SymI_HasProto(stopTimer) \ SymI_HasProto(n_capabilities) \ ===================================== rts/include/rts/Constants.h ===================================== @@ -328,6 +328,12 @@ */ #define TSO_ALLOC_LIMIT 256 +/* + * Enables step-in mode for this thread -- it will stop at the immediate next + * breakpoint found in this thread. + */ +#define TSO_STOP_NEXT_BREAKPOINT 512 + /* * The number of times we spin in a spin lock before yielding (see * #3758). To tune this value, use the benchmark in #3758: run the View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/9ffc8223b6e9391e5ffbcba2f2098c1… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/9ffc8223b6e9391e5ffbcba2f2098c1… You're receiving this email because of your account on gitlab.haskell.org.
1 0
0 0
  • ← Newer
  • 1
  • ...
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • ...
  • 116
  • Older →

HyperKitty Powered by HyperKitty version 1.3.9.