Package: emacs;
Reported by: Óscar Fuentes <oscarfv <at> telefonica.net>
Date: Tue, 26 Nov 2024 18:36:02 UTC
Severity: normal
Found in version 31.0.50
Done: Óscar Fuentes <oscarfv <at> telefonica.net>
Bug is archived. No further changes may be made.
To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 74547 in the body.
You can then email your comments to 74547 AT debbugs.gnu.org in the normal way.
Toggle the display of automated, internal messages from the tracker.
View this report as an mbox folder, status mbox, maintainer mbox
bug-gnu-emacs <at> gnu.org
:bug#74547
; Package emacs
.
(Tue, 26 Nov 2024 18:36:02 GMT) Full text and rfc822 format available.Óscar Fuentes <oscarfv <at> telefonica.net>
:bug-gnu-emacs <at> gnu.org
.
(Tue, 26 Nov 2024 18:36:02 GMT) Full text and rfc822 format available.Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):
From: Óscar Fuentes <oscarfv <at> telefonica.net> To: bug-gnu-emacs <at> gnu.org Subject: 31.0.50; igc: assertion failed in buffer.c Date: Tue, 26 Nov 2024 19:35:00 +0100
While editing a .dart file with lsp-mode. gdb) bt full #0 terminate_due_to_signal (sig=6, backtrace_limit=2147483647) at ../../emacs/src/emacs.c:433 #1 0x00005555559038cf in set_state (state=IGC_STATE_DEAD) at ../../emacs/src/igc.c:858 old_state = IGC_STATE_USABLE #2 0x0000555555902f3e in igc_assert_fail (file=0x555555a47782 "buffer.c", line=579, msg=0x555555a4a157 "size > 0") at ../../emacs/src/igc.c:209 #3 0x00005555559c1384 in mps_lib_assert_fail (condition=0x555555a4a157 "size > 0", line=579, file=0x555555a47782 "buffer.c") at /home/oscar/dev/other/mps/code/mpsliban.c:87 #4 BufferFill (pReturn=pReturn <at> entry=0x7fffffff9988, buffer=buffer <at> entry=0x7fffe8000578, size=size <at> entry=0) at /home/oscar/dev/other/mps/code/buffer.c:579 res = <optimized out> pool = <optimized out> base = 0x7fff93f2f7d0 limit = 0x1 next = <optimized out> #5 0x00005555559f2da0 in amcSegFix (seg=0x7fffb820d070, ss=0x7fffffff9fc0, refIO=0x7fffffff99d0) at /home/oscar/dev/other/mps/code/poolamc.c:1633 clientQ = <optimized out> arena = 0x7ffff7fbf000 pool = <optimized out> amc = <optimized out> res = <optimized out> format = 0x7fffe8000388 headerSize = 0 --Type <RET> for more, q to quit, c to continue without paging-- ref = <optimized out> base = <optimized out> newRef = <optimized out> newBase = 0x7fff8a259f28 length = 0 buffer = 0x7fffe8000578 gen = <optimized out> grey = <optimized out> toSeg = <optimized out> ti = <optimized out> trace = <optimized out> #6 0x0000555555990b8c in _mps_fix2 (mps_ss=0x7fffffff9fc8, mps_ref_io=0x7fffffff9a10) at /home/oscar/dev/other/mps/code/trace.c:1433 ss = 0x7fffffff9fc0 ref = 0x7fff93f2f7d0 chunk = 0x7fff84000000 i = <optimized out> tract = <optimized out> seg = <optimized out> res = <optimized out> #7 0x0000555555903cac in fix_lisp_obj (ss=0x7fffffff9fc8, pobj=0x7fff89f0e000) at ../../emacs/src/igc.c:998 res = 32767 client = 0x7fff93f2f7d0 base = 0x7fff93f2f7d0 p = 0x7fff89f0e000 --Type <RET> for more, q to quit, c to continue without paging-- word = 140735675561940 tag = 4 _ss = 0x7fffffff9fc8 _mps_zs = 22 _mps_ufs = 549755846664 _mps_wt = 32768 _mps_w = 133143986160 #8 0x0000555555904160 in fix_array (ss=0x7fffffff9fc8, array=0x7fff89f0e000, n=6) at ../../emacs/src/igc.c:1233 res = 30 i = 0 _ss = 0x7fffffff9fc8 _mps_zs = 22 _mps_ufs = 549755813896 _mps_wt = <optimized out> _mps_w = 133143986160 #9 0x000055555590674b in fix_vectorlike (ss=0x7fffffff9fc8, v=0x7fff89f0dff0) at ../../emacs/src/igc.c:1974 res = 32767 size = 6 _ss = 0x7fffffff9fc8 _mps_zs = 22 _mps_ufs = 549755813896 _mps_wt = <optimized out> _mps_w = 133143986160 #10 0x0000555555908d53 in fix_vector (ss=0x7fffffff9fc8, v=0x7fff89f0dff0) --Type <RET> for more, q to quit, c to continue without paging-- at ../../emacs/src/igc.c:2646 obj_ = 0x7fff89f0dff0 res = 0 _ss = 0x7fffffff9fc8 _mps_zs = 22 _mps_ufs = 549755813896 _mps_wt = <optimized out> _mps_w = 133143986160 #11 0x00005555559061d4 in dflt_scan_obj (ss=0x7fffffff9fc8, base_start=0x7fff89f0dff0, base_limit=0x7fff89f0f000, closure=0x0) at ../../emacs/src/igc.c:1888 obj_ = 0x7fff89f0dff0 res = 0 base = 0x7fff89f0dff0 client = 0x7fff89f0dff0 header = 0x7fff89f0dff0 _ss = 0x7fffffff9fc8 _mps_zs = 22 _mps_ufs = 549755813896 _mps_wt = <optimized out> _mps_w = 133143986160 #12 0x0000555555906619 in dflt_scanx (ss=0x7fffffff9fc8, base_start=0x7fff89f0d000, base_limit=0x7fff89f0f000, closure=0x0) at ../../emacs/src/igc.c:1951 res = 0 base = 0x7fff89f0dff0 --Type <RET> for more, q to quit, c to continue without paging-- _ss = 0x7fffffff9fc8 _mps_zs = 22 _mps_ufs = 549755813896 _mps_wt = <optimized out> _mps_w = 133143986160 #13 0x00005555559066b8 in dflt_scan (ss=0x7fffffff9fc8, base_start=0x7fff89f0d000, base_limit=0x7fff89f0f000) at ../../emacs/src/igc.c:1962 res = 0 _ss = 0x7fffffff9fc8 _mps_zs = 22 _mps_ufs = 0 _mps_wt = <optimized out> _mps_w = 133143986160 #14 0x00005555559c25bf in TraceScanFormat (limit=0x7fff89f0f000, base=0x7fff89f0d000, ss=0x7fffffff9fc0) at /home/oscar/dev/other/mps/code/trace.c:1539 #15 amcSegScan (totalReturn=0x7fffffff9fbc, seg=0x7fffb82b3340, ss=0x7fffffff9fc0) at /home/oscar/dev/other/mps/code/poolamc.c:1440 base = 0x7fff89f0d000 limit = 0x7fff89f0f000 format = 0x7fffe8000388 pool = <optimized out> amc = <optimized out> res = <optimized out> buffer = 0x5555559bf6d8 <SegScan+56> --Type <RET> for more, q to quit, c to continue without paging-- #16 0x00005555559ee4f9 in traceScanSegRes (ts=ts <at> entry=1, rank=rank <at> entry=1, arena=arena <at> entry=0x7ffff7fbf000, seg=seg <at> entry=0x7fffb82b3340) at /home/oscar/dev/other/mps/code/trace.c:1205 ssStruct = { sig = 1368771141, ss_s = { _zs = 22, _w = 133143986160, _ufs = 549755813896 }, arena = 0x7ffff7fbf000, formatScan = 0x555555906660 <dflt_scan>, areaScan = 0x555555980ca0 <traceNoAreaScan>, areaScanClosure = 0x7ffff7fbf000, fix = 0x555555982120 <SegFix>, fixClosure = 0x0, traces = 1, rank = 1, wasMarked = 0, fixedSummary = 0, scannedSize = 8192 } ss = 0x7fffffff9fc0 wasTotal = 1 white = 133143986160 res = <optimized out> --Type <RET> for more, q to quit, c to continue without paging-- #17 0x00005555559ee6ea in traceScanSeg (ts=1, rank=1, arena=0x7ffff7fbf000, seg=0x7fffb82b3340) at /home/oscar/dev/other/mps/code/trace.c:1267 res = <optimized out> #18 0x00005555559ef0c4 in TraceAdvance (trace=trace <at> entry=0x7ffff7fbfaa8) at /home/oscar/dev/other/mps/code/trace.c:1728 res = <optimized out> seg = 0x7fffb82b3340 rank = 1 arena = <optimized out> oldWork = <optimized out> newWork = <optimized out> #19 0x00005555559ef754 in TracePoll (workReturn=workReturn <at> entry=0x7fffffffa198, collectWorldReturn=collectWorldReturn <at> entry=0x7fffffffa194, globals=globals <at> entry=0x7ffff7fbf008, collectWorldAllowed=<optimized out>) at /home/oscar/dev/other/mps/code/trace.c:1849 trace = 0x7ffff7fbfaa8 arena = 0x7ffff7fbf000 oldWork = 21021000 newWork = <optimized out> work = <optimized out> endWork = 21201780 #20 0x00005555559ef94b in ArenaPoll (globals=globals <at> entry=0x7ffff7fbf008) at /home/oscar/dev/other/mps/code/global.c:745 arena = 0x7ffff7fbf000 start = 127960946 worldCollected = 0 --Type <RET> for more, q to quit, c to continue without paging-- moreWork = <optimized out> workWasDone = 1 tracedWork = 188224 #21 0x00005555559efce7 in mps_ap_fill (p_o=0x7fffffffa320, mps_ap=0x7fffe8001980, size=24) at /home/oscar/dev/other/mps/code/mpsi.c:1097 _sc = { jumpBuffer = {{ __jmpbuf = {140737085708576, 7934441737627226205, 140737488341000, 140737488346136, 93825011090592, 93824998081432, 7934441737587380317, 4272113373193949277}, __mask_was_saved = 0, __saved_mask = { __val = {8589988184, 140735675617355, 53592, 93824998129552, 46912143837648, 8, 1216, 140735675620139, 53592, 93825011044696, 53592, 93824998129552, 8, 24, 140737488331504, 93824996095173} } }} } buf = 0x7fffe8001920 arena = 0x7ffff7fbf000 p = 0xd158 res = <optimized out> #22 0x000055555590b0c2 in alloc_impl (size=24, type=IGC_OBJ_CONS, ap=0x7fffe8001980) at ../../emacs/src/igc.c:3802 res = 21845 p = 0x0 #23 0x000055555590b1b4 in alloc (size=24, type=IGC_OBJ_CONS) at ../../emacs/src/igc.c:3830 #24 0x000055555590b267 in igc_make_cons (car=XIL(0x2aaa95ab49d0), cdr=XIL(0x7fffeccdc75c)) --Type <RET> for more, q to quit, c to continue without paging-- at ../../emacs/src/igc.c:3859 cons = 0x0 #25 0x00005555558022c0 in Fcons (car=XIL(0x2aaa95ab49d0), cdr=XIL(0x7fffeccdc75c)) at ../../emacs/src/alloc.c:2955 #26 0x0000555555842ced in funcall_lambda (fun=XIL(0x7fff93f3e2a5), nargs=1, arg_vector=0x7fffffffa5d8) at ../../emacs/src/eval.c:3324 arg = XIL(0x7fffeccdc75c) next = XIL(0x2aaa95ab49d0) syms_left = XIL(0x7fffec95ce6b) lexenv = XIL(0x7fffc0fb14cb) count = { bytes = 1152 } i = 1 optional = false rest = false previous_rest = false val = XIL(0) #27 0x0000555555841da2 in funcall_general (fun=XIL(0x7fff93f3e2a5), numargs=1, args=0x7fffffffa5d8) at ../../emacs/src/eval.c:3050 original_fun = XIL(0x7fff93f3e2a5) #28 0x0000555555842064 in Ffuncall (nargs=2, args=0x7fffffffa5d0) at ../../emacs/src/eval.c:3099 count = { bytes = 1120 } val = XIL(0) --Type <RET> for more, q to quit, c to continue without paging-- #29 0x0000555555854850 in mapcar1 (leni=15, vals=0x7fffffffa660, fn=XIL(0x7fff93f3e2a5), seq=XIL(0x7fff93f3e44b)) at ../../emacs/src/fns.c:3373 dummy = XIL(0) i = 12 tail = XIL(0x7fff93f3e56b) #30 0x0000555555854fde in Fmapcar (function=XIL(0x7fff93f3e2a5), sequence=XIL(0x7fff93f3e44b)) at ../../emacs/src/fns.c:3493 sa_avail = 16264 sa_count = { bytes = 1120 } leni = 15 args = 0x7fffffffa660 nmapped = 140737488332592 ret = XIL(0x555555839828) #31 0x0000555555840b20 in eval_sub (form=XIL(0x7fffeded0a33)) at ../../emacs/src/eval.c:2607 i = 2 maxargs = 2 args_left = XIL(0) numargs = 2 original_fun = XIL(0x2aaa6a8789a0) original_args = XIL(0x7fffeded0cab) count = { bytes = 1088 } --Type <RET> for more, q to quit, c to continue without paging-- fun = XIL(0x5555566b7265) val = XIL(0x7fffffffa800) funcar = XIL(0) argvals = {XIL(0x7fff93f3e2a5), XIL(0x7fff93f3e44b), XIL(0x2420000026600), XIL(0x2440000027000), XIL(0x555556ae8628), XIL(0x7ffff76dc739), XIL(0x555556738000), XIL(0)} #32 0x000055555583ceb5 in Flet (args=XIL(0x7fffedecf953)) at ../../emacs/src/eval.c:1084 temps = 0x7fffffffa870 tem = XIL(0x5555566b47a5) lexenv = XIL(0x135584a4ab) elt = XIL(0x7fffeded0283) count = { bytes = 1088 } argnum = 0 sa_avail = 16368 sa_count = { bytes = 1088 } varlist = XIL(0x7fffeded029b) varlist_len = 2 nvars = 2 #33 0x0000555555840798 in eval_sub (form=XIL(0x7fffedecf2cb)) at ../../emacs/src/eval.c:2555 args_left = XIL(0x7fffedecf953) numargs = 2 original_fun = XIL(0xe1c0) original_args = XIL(0x7fffedecf953) --Type <RET> for more, q to quit, c to continue without paging-- count = { bytes = 1056 } fun = XIL(0x5555566b47a5) val = XIL(0x7fffb61b20b0) funcar = XIL(0x555555af3f90) argvals = {XIL(0x1ffffa9d0), XIL(0), XIL(0x7fff93f3d04b), XIL(0xd158), XIL(0x5555558179e4), XIL(0x555555af3f90), XIL(0x7fffffffa9e0), XIL(0x555555817afb)} #34 0x000055555583b494 in Fprogn (body=XIL(0x7fffedecf2e3)) at ../../emacs/src/eval.c:443 form = XIL(0x7fffedecf2cb) val = XIL(0) #35 0x000055555583d0a8 in Flet (args=XIL(0x7fffedecddfb)) at ../../emacs/src/eval.c:1113 temps = 0x7fffffffaa90 tem = XIL(0) lexenv = XIL(0x7fff93f3d04b) elt = XIL(0x2aaa97797290) count = { bytes = 1024 } argnum = 1 sa_avail = 16376 sa_count = { bytes = 1024 } varlist = XIL(0) varlist_len = 1 --Type <RET> for more, q to quit, c to continue without paging-- nvars = 1 #36 0x0000555555840798 in eval_sub (form=XIL(0x7fffedecd043)) at ../../emacs/src/eval.c:2555 args_left = XIL(0x7fffedecddfb) numargs = 3 original_fun = XIL(0xe1c0) original_args = XIL(0x7fffedecddfb) count = { bytes = 992 } fun = XIL(0x5555566b47a5) val = XIL(0x555555848d14) funcar = XIL(0x7fffffffac10) argvals = {XIL(0x7fffffffad80), XIL(0x555555981480), XIL(0x555556738000), XIL(0), XIL(0), XIL(0x7fffffffabe0), make_fixnum(23456248831157), XIL(0)} #37 0x0000555555840a3e in eval_sub (form=XIL(0x7fffede44f43)) at ../../emacs/src/eval.c:2592 i = 0 maxargs = 1 args_left = XIL(0x7fffede4724b) numargs = 1 original_fun = XIL(0x2aaa6a87dd60) original_args = XIL(0x7fffede4724b) count = { bytes = 960 } fun = XIL(0x5555566b6cc5) val = XIL(0x7fffffffad30) --Type <RET> for more, q to quit, c to continue without paging-- funcar = XIL(0) argvals = {XIL(0x7fffe8011458), XIL(0x7fffffffada8), XIL(0x5555559813c0), XIL(0x5555559813e0), XIL(0x7fffffffad98), XIL(0x7fffffffaea0), XIL(0x555556738000), XIL(0)} #38 0x0000555555842835 in apply_lambda (fun=XIL(0x7fffbc35adc5), args=XIL(0x7fffede44c4b), count=...) at ../../emacs/src/eval.c:3216 i = 0 arg_vector = 0x7fffffffada0 tem = XIL(0x7fffede44f43) sa_avail = 16368 sa_count = { bytes = 960 } numargs = 2 args_left = XIL(0x7fffede44f5b) #39 0x0000555555840d36 in eval_sub (form=XIL(0x7fffede4495b)) at ../../emacs/src/eval.c:2651 original_fun = XIL(0x2aaa961a0fa8) original_args = XIL(0x7fffede44c4b) count = { bytes = 928 } fun = XIL(0x7fffbc35adc5) val = XIL(0x7fffb61b20b0) funcar = XIL(0x555555af3f90) argvals = {XIL(0x184183dd0), XIL(0), XIL(0x7fffec29f443), XIL(0xd158), XIL(0x5555558179e4), XIL(0x555555af3f90), XIL(0x7fffffffaee0), XIL(0x555555817afb)} #40 0x000055555583b494 in Fprogn (body=XIL(0)) at ../../emacs/src/eval.c:443 --Type <RET> for more, q to quit, c to continue without paging-- form = XIL(0x7fffede4495b) val = XIL(0) #41 0x0000555555842f49 in funcall_lambda (fun=XIL(0x7fffede44245), nargs=0, arg_vector=0x7fffffffb020) at ../../emacs/src/eval.c:3356 syms_left = XIL(0) lexenv = XIL(0x7fffec29f443) count = { bytes = 896 } i = 0 optional = false rest = false previous_rest = false val = XIL(0x23) #42 0x000055555584289b in apply_lambda (fun=XIL(0x7fffede44245), args=XIL(0), count=...) at ../../emacs/src/eval.c:3221 arg_vector = 0x7fffffffb020 tem = XIL(0x219770bee0) sa_avail = 16384 sa_count = { bytes = 896 } numargs = 0 args_left = XIL(0) #43 0x0000555555840d36 in eval_sub (form=XIL(0x7fffede43b9b)) at ../../emacs/src/eval.c:2651 original_fun = XIL(0x2aaa9770bee0) --Type <RET> for more, q to quit, c to continue without paging-- original_args = XIL(0) count = { bytes = 864 } fun = XIL(0x7fffede44245) val = XIL(0x7fff93f3cfc0) funcar = make_fixnum(23456248816738) argvals = {XIL(0x7fffffffb150), XIL(0x55555584f9f5), XIL(0x7fff93f3cfdb), XIL(0x2aaa961dc2d8), XIL(0x555556738000), XIL(0), XIL(0), XIL(0x7fff93f3cfc3)} #44 0x000055555583cac0 in FletX (args=XIL(0x7fffec978b93)) at ../../emacs/src/eval.c:1021 li = { tortoise = XIL(0x7fffec978c13), max = 2, n = 0, q = 2 } var = XIL(0x2aaa9a427760) val = XIL(0x7fffffffb250) elt = XIL(0x7fffede43543) lexenv = XIL(0x7fff93f3d01b) count = { bytes = 864 } varlist = XIL(0x7fffec978c13) #45 0x0000555555840798 in eval_sub (form=XIL(0x7fffec978b33)) at ../../emacs/src/eval.c:2555 args_left = XIL(0x7fffec978b93) --Type <RET> for more, q to quit, c to continue without paging-- numargs = 2 original_fun = XIL(0xe1f8) original_args = XIL(0x7fffec978b93) count = { bytes = 832 } fun = XIL(0x5555566b4745) val = XIL(0x5555567504a0) funcar = XIL(0x7fffffffdc18) argvals = {XIL(0x7ffff7fbf000), XIL(0x5555559e601c), XIL(0x18), XIL(0x7fffe80003f8), XIL(0x7fffffffb398), XIL(0x7ffff7fbf000), XIL(0x7fffe8000110), XIL(0x7fffffffc808)} #46 0x000055555583b34d in Fif (args=XIL(0x7fffec978a53)) at ../../emacs/src/eval.c:398 cond = XIL(0x38) #47 0x0000555555840798 in eval_sub (form=XIL(0x7fffec9789cb)) at ../../emacs/src/eval.c:2555 args_left = XIL(0x7fffec978a53) numargs = 3 original_fun = XIL(0xc6a0) original_args = XIL(0x7fffec978a53) count = { bytes = 800 } fun = XIL(0x5555566b40e5) val = make_fixnum(23456249031744) funcar = XIL(0x7fffffffb4b0) argvals = {XIL(0x7fffffffb470), make_fixnum(23456249023624), XIL(0x5b4ad3), XIL(0x18), XIL(0x300000018), XIL(0x7fff93f3d018), XIL(0x18), XIL(0x1)} --Type <RET> for more, q to quit, c to continue without paging-- #48 0x000055555583b494 in Fprogn (body=XIL(0)) at ../../emacs/src/eval.c:443 form = XIL(0x7fffec9789cb) val = XIL(0) #49 0x000055555583ccb0 in FletX (args=XIL(0x7fffec97874b)) at ../../emacs/src/eval.c:1046 var = XIL(0x2aaa96240a98) val = XIL(0x38) elt = XIL(0x7fffec978a3b) lexenv = XIL(0x7fffec29f443) count = { bytes = 768 } varlist = XIL(0) #50 0x0000555555840798 in eval_sub (form=XIL(0x7fffec978693)) at ../../emacs/src/eval.c:2555 args_left = XIL(0x7fffec97874b) numargs = 2 original_fun = XIL(0xe1f8) original_args = XIL(0x7fffec97874b) count = { bytes = 736 } fun = XIL(0x5555566b4745) val = XIL(0x55555669b880) funcar = XIL(0x7fffffffb670) argvals = {XIL(0x7fffffffb650), XIL(0x7fffe8001980), XIL(0x300000000), XIL(0x18), XIL(0x555556738000), XIL(0), XIL(0), XIL(0x2e0)} #51 0x000055555583de53 in internal_lisp_condition_case --Type <RET> for more, q to quit, c to continue without paging-- (var=XIL(0), bodyform=XIL(0x7fffec978693), handlers=XIL(0x7fffec9786ab)) at ../../emacs/src/eval.c:1544 clause = XIL(0x7fffec978763) condition = XIL(0x7fff93f3cf7b) c = 0x7fffefb28298 clauses_volatile = 0x7fffffffb6f0 pcl = 0x7fffffffb6f8 oldhandlerlist = 0x7fffec0289e8 clausenb = 2 success_handler = XIL(0) clauses = 0x7fffffffb6f0 var_volatile = XIL(0) val = XIL(0x7fffffffb7a0) handler_body = XIL(0x555556deab60) count = { bytes = 736 } #52 0x000055555583d951 in Fcondition_case (args=XIL(0x7fffec9783d3)) at ../../emacs/src/eval.c:1443 var = XIL(0) bodyform = XIL(0x7fffec978693) handlers = XIL(0x7fffec9786ab) #53 0x0000555555840798 in eval_sub (form=XIL(0x7fffec9781b3)) at ../../emacs/src/eval.c:2555 args_left = XIL(0x7fffec9783d3) numargs = 3 original_fun = XIL(0x6f20) original_args = XIL(0x7fffec9783d3) --Type <RET> for more, q to quit, c to continue without paging-- count = { bytes = 704 } fun = XIL(0x5555566b4a45) val = XIL(0x7fffb61b20b0) funcar = XIL(0x555555af3f90) argvals = {XIL(0x193f3cea3), XIL(0), XIL(0x7fffec29f443), XIL(0xd158), XIL(0x5555558179e4), XIL(0x555555af3f90), XIL(0x7fffffffb8f0), XIL(0x555555817afb)} #54 0x000055555583b494 in Fprogn (body=XIL(0)) at ../../emacs/src/eval.c:443 form = XIL(0x7fffec9781b3) val = XIL(0) #55 0x0000555555842f49 in funcall_lambda (fun=XIL(0x7fffec977e75), nargs=0, arg_vector=0x7fffffffba30) at ../../emacs/src/eval.c:3356 syms_left = XIL(0) lexenv = XIL(0x7fffec29f443) count = { bytes = 672 } i = 0 optional = false rest = false previous_rest = false val = make_fixnum(34910567923712) #56 0x000055555584289b in apply_lambda (fun=XIL(0x7fffec977e75), args=XIL(0), count=...) at ../../emacs/src/eval.c:3221 arg_vector = 0x7fffffffba30 --Type <RET> for more, q to quit, c to continue without paging-- tem = XIL(0x219623fc48) sa_avail = 16384 sa_count = { bytes = 672 } numargs = 0 args_left = XIL(0) #57 0x0000555555840d36 in eval_sub (form=XIL(0x7fffec977a23)) at ../../emacs/src/eval.c:2651 original_fun = XIL(0x2aaa9623fc48) original_args = XIL(0) count = { bytes = 640 } fun = XIL(0x7fffec977e75) val = XIL(0x4590) funcar = XIL(0x7fffffffbb80) argvals = {XIL(0x280), XIL(0x280), XIL(0x555556738000), XIL(0), XIL(0), XIL(0x7fffffffbb50), make_fixnum(23456248831157), XIL(0xffffbb60)} #58 0x0000555555840a3e in eval_sub (form=XIL(0x7fffec976bfb)) at ../../emacs/src/eval.c:2592 i = 2 maxargs = 3 args_left = XIL(0x7fffec97776b) numargs = 3 original_fun = XIL(0x2aaa958f80b0) original_args = XIL(0x7fffec977003) count = { --Type <RET> for more, q to quit, c to continue without paging-- bytes = 608 } fun = XIL(0x5555566ab025) val = XIL(0) funcar = XIL(0x555555af3f90) argvals = {XIL(0x7fffed4cb0ad), XIL(0x4590), XIL(0x7fff93f3cf63), XIL(0xd158), XIL(0x5555558179e4), XIL(0x555555af3f90), XIL(0x7fffffffbc90), XIL(0x555555817afb)} #59 0x000055555583b494 in Fprogn (body=XIL(0)) at ../../emacs/src/eval.c:443 form = XIL(0x7fffec976bfb) val = XIL(0) #60 0x000055555583d0a8 in Flet (args=XIL(0x7fffec97615b)) at ../../emacs/src/eval.c:1113 temps = 0x7fffffffbd40 tem = make_fixnum(0) lexenv = XIL(0x7fff93f3cf63) elt = XIL(0x7fffec976be3) count = { bytes = 576 } argnum = 2 sa_avail = 16368 sa_count = { bytes = 576 } varlist = XIL(0) varlist_len = 2 nvars = 2 --Type <RET> for more, q to quit, c to continue without paging-- #61 0x0000555555840798 in eval_sub (form=XIL(0x7fffec975e3b)) at ../../emacs/src/eval.c:2555 args_left = XIL(0x7fffec97615b) numargs = 3 original_fun = XIL(0xe1c0) original_args = XIL(0x7fffec97615b) count = { bytes = 544 } fun = XIL(0x5555566b47a5) val = XIL(0x7ffff7fbf000) funcar = XIL(0x7fffec975e23) argvals = {XIL(0x7ffff7fbf000), XIL(0x7fffbe437045), XIL(0x7fffe0a702c0), XIL(0x7ffff7fbf658), XIL(0x7ffff7fbf000), XIL(0x5555559e601c), XIL(0x7fffb817a3a8), XIL(0x5555559ed408)} #62 0x000055555583b494 in Fprogn (body=XIL(0x7fffec975e53)) at ../../emacs/src/eval.c:443 form = XIL(0x7fffec975e3b) val = XIL(0) #63 0x000055555583b4c4 in prog_ignore (body=XIL(0x7fffec975b23)) at ../../emacs/src/eval.c:454 #64 0x000055555583d111 in Fwhile (args=XIL(0x7fffec975683)) at ../../emacs/src/eval.c:1134 test = XIL(0x7fffec975b0b) body = XIL(0x7fffec975b23) #65 0x0000555555840798 in eval_sub (form=XIL(0x7fffec9751f3)) at ../../emacs/src/eval.c:2555 args_left = XIL(0x7fffec975683) numargs = 3 original_fun = XIL(0x2aaa95906448) original_args = XIL(0x7fffec975683) count = { --Type <RET> for more, q to quit, c to continue without paging-- bytes = 512 } fun = XIL(0x5555566b4805) val = XIL(0x7fffb61b20b0) funcar = XIL(0x555555af3f90) argvals = {XIL(0x1ffffc060), XIL(0), XIL(0x7fff93f3cea3), XIL(0xd158), XIL(0x5555558179e4), XIL(0x555555af3f90), XIL(0x7fffffffc070), XIL(0x555555817afb)} #66 0x000055555583b494 in Fprogn (body=XIL(0)) at ../../emacs/src/eval.c:443 form = XIL(0x7fffec9751f3) val = XIL(0) #67 0x000055555583d0a8 in Flet (args=XIL(0x7fffec974853)) at ../../emacs/src/eval.c:1113 temps = 0x7fffffffc120 tem = XIL(0) lexenv = XIL(0x7fff93f3cea3) elt = XIL(0x2aaa9623dad0) count = { bytes = 480 } argnum = 3 sa_avail = 16360 sa_count = { bytes = 480 } varlist = XIL(0) varlist_len = 3 nvars = 3 --Type <RET> for more, q to quit, c to continue without paging-- #68 0x0000555555840798 in eval_sub (form=XIL(0x7fffec974333)) at ../../emacs/src/eval.c:2555 args_left = XIL(0x7fffec974853) numargs = 2 original_fun = XIL(0xe1c0) original_args = XIL(0x7fffec974853) count = { bytes = 448 } fun = XIL(0x5555566b47a5) val = XIL(0x7fffffffc2a0) funcar = XIL(0) argvals = {XIL(0x7fff93f3cdd3), XIL(0x7fff93f3cd73), XIL(0x7fff93f3cdd3), XIL(0x7fff93f3cd73), XIL(0), make_fixnum(1000000000000), XIL(0x555556738000), XIL(0)} #69 0x000055555583b494 in Fprogn (body=XIL(0)) at ../../emacs/src/eval.c:443 form = XIL(0x7fffec974333) val = XIL(0) #70 0x000055555583b36f in Fif (args=XIL(0x7fffec973573)) at ../../emacs/src/eval.c:399 cond = XIL(0) #71 0x0000555555840798 in eval_sub (form=XIL(0x7fffec973133)) at ../../emacs/src/eval.c:2555 args_left = XIL(0x7fffec973573) numargs = 3 original_fun = XIL(0xc6a0) original_args = XIL(0x7fffec973573) count = { bytes = 416 } --Type <RET> for more, q to quit, c to continue without paging-- fun = XIL(0x5555566b40e5) val = XIL(0x7fffb61b20b0) funcar = XIL(0x555555af3f90) argvals = {XIL(0x1ffffc400), XIL(0), XIL(0x7fffec29f443), XIL(0xd158), XIL(0x5555558179e4), XIL(0x555555af3f90), XIL(0x7fffffffc430), XIL(0x555555817afb)} #72 0x000055555583b494 in Fprogn (body=XIL(0)) at ../../emacs/src/eval.c:443 form = XIL(0x7fffec973133) val = XIL(0) #73 0x0000555555842f49 in funcall_lambda (fun=XIL(0x7fffec9726bd), nargs=0, arg_vector=0x7fffffffc818) at ../../emacs/src/eval.c:3356 syms_left = XIL(0) lexenv = XIL(0x7fffec29f443) count = { bytes = 384 } i = 0 optional = false rest = false previous_rest = false val = XIL(0x555555ae8398) #74 0x0000555555841da2 in funcall_general (fun=XIL(0x7fffec9726bd), numargs=0, args=0x7fffffffc818) at ../../emacs/src/eval.c:3050 original_fun = XIL(0x2aaa9623a0a0) #75 0x0000555555842064 in Ffuncall (nargs=1, args=0x7fffffffc810) at ../../emacs/src/eval.c:3099 count = { bytes = 352 --Type <RET> for more, q to quit, c to continue without paging-- } val = make_fixnum(0) #76 0x000055555584112d in Fapply (nargs=2, args=0x7fffffffc810) at ../../emacs/src/eval.c:2724 i = 140736340922707 funcall_nargs = 56 funcall_args = 0x0 spread_arg = XIL(0) fun = XIL(0x2aaa9623a0a0) sa_avail = 16384 sa_count = { bytes = 352 } numargs = 0 retval = XIL(0x567d38e0) #77 0x00005555558425ee in funcall_subr (subr=0x5555566b4ce0 <Sapply>, numargs=2, args=0x7fffffffc810) at ../../emacs/src/eval.c:3190 maxargs = -2 fun = XIL(0x555555839828) #78 0x0000555555841d56 in funcall_general (fun=XIL(0x5555566b4ce5), numargs=2, args=0x7fffffffc810) at ../../emacs/src/eval.c:3046 original_fun = XIL(0x48a0) #79 0x0000555555842064 in Ffuncall (nargs=3, args=0x7fffffffc808) at ../../emacs/src/eval.c:3099 count = { bytes = 320 } val = make_fixnum(23456248827543) --Type <RET> for more, q to quit, c to continue without paging-- #80 0x00007fffe0a652c9 in F74696d65722d6576656e742d68616e646c6572_timer_event_handler_0 () at /home/oscar/dev/emacs/igc-debug/src/../native-lisp/31.0.50-25e6c268/preloaded/timer-3ee7cfd9-faf18a90.eln #81 0x0000555555842394 in funcall_subr (subr=0x7fffec024b60, numargs=1, args=0x7fffffffc9c8) at ../../emacs/src/eval.c:3167 argbuf = {XIL(0x7fffec024b65), XIL(0x7fffffffc8b0), XIL(0x555556738000), XIL(0), XIL(0), XIL(0x13ffffc8d0), XIL(0x7fffec024b65), XIL(0x7fffffffc8e0)} a = 0x7fffffffc9c8 maxargs = 1 fun = XIL(0x555555839828) #82 0x0000555555841d56 in funcall_general (fun=XIL(0x7fffec024b65), numargs=1, args=0x7fffffffc9c8) at ../../emacs/src/eval.c:3046 original_fun = XIL(0x150e0) #83 0x0000555555842064 in Ffuncall (nargs=2, args=0x7fffffffc9c0) at ../../emacs/src/eval.c:3099 count = { bytes = 224 } val = XIL(0x150e0) #84 0x000055555576e3e2 in timer_check_2 (timers=XIL(0x7fff93f3c8cb), idle_timers=XIL(0x7fff93f3c95b)) at ../../emacs/src/keyboard.c:4820 count = { bytes = 192 } old_deactivate_mark = XIL(0) chosen_timer = XIL(0x7fffbe437045) timer = XIL(0x7fffbe437045) --Type <RET> for more, q to quit, c to continue without paging-- idle_timer = XIL(0x7fffedd1d0c5) ripe = true timer_ripe = true idle_timer_ripe = true difference = { tv_sec = 0, tv_nsec = 527695107 } timer_difference = { tv_sec = 0, tv_nsec = 527695107 } idle_timer_difference = { tv_sec = 0, tv_nsec = 511956257 } now = { tv_sec = 1732645572, tv_nsec = 273958132 } idleness_now = { tv_sec = 0, tv_nsec = 636956257 } #85 0x000055555576e527 in timer_check () at ../../emacs/src/keyboard.c:4885 nexttime = { --Type <RET> for more, q to quit, c to continue without paging-- tv_sec = 93824995782329, tv_nsec = 363641187 } timers = XIL(0x7fff93f3c8b3) idle_timers = XIL(0x7fff93f3c943) tem = XIL(0) #86 0x00005555558c556b in wait_reading_process_output (time_limit=30, nsecs=0, read_kbd=-1, do_display=true, wait_for_cell=XIL(0), wait_proc=0x0, just_wait_proc=0) at ../../emacs/src/process.c:5433 old_timers_run = 5142 process_skipped = false wrapped = true channel_start = 21 child_fd = 13 last_read_channel = 20 channel = 21 nfds = 1 Available = { fds_bits = {0 <repeats 16 times>} } Writeok = { fds_bits = {0 <repeats 16 times>} } check_write = true check_delay = 2 no_avail = false --Type <RET> for more, q to quit, c to continue without paging-- xerrno = 11 proc = XIL(0x7fffec0a9005) timeout = { tv_sec = 29, tv_nsec = 363641187 } end_time = { tv_sec = 1732645601, tv_nsec = 637403875 } timer_delay = { tv_sec = 0, tv_nsec = 75496097 } got_output_end_time = { tv_sec = 0, tv_nsec = -1 } wait = TIMEOUT got_some_output = 111340 prev_wait_proc_nbytes_read = 0 retry_for_async = false count = { bytes = 160 } now = { --Type <RET> for more, q to quit, c to continue without paging-- tv_sec = 1732645572, tv_nsec = 273762688 } #87 0x00005555555b3552 in sit_for (timeout=make_fixnum(30), reading=true, display_option=1) at ../../emacs/src/dispnew.c:6362 sec = 30 nsec = 0 do_display = true curbuf_eq_winbuf = true nbytes = 21845 #88 0x0000555555769966 in read_char (commandflag=1, map=XIL(0x7fff93a23273), prev_event=XIL(0), used_mouse_menu=0x7fffffffd41f, end_time=0x0) at ../../emacs/src/keyboard.c:2937 tem0 = XIL(0xca90) timeout = 30 count1 = { bytes = 128 } delay_level = 4 buffer_size = 54 c = XIL(0) local_getcjmp = {{ __jmpbuf = {0, 7934441734953357405, 0, 140737488346136, 140737354125312, 93824998081432, 7934441734561189981, 4272114679796584541}, __mask_was_saved = 0, __saved_mask = { --Type <RET> for more, q to quit, c to continue without paging-- __val = {93824996094498, 5850328, 24, 12884901912, 140735670268528, 24, 1, 140737488343728, 93824996126978, 0, 140737085708672, 17179857584, 24, 140735670268528, 1451047136, 17179857616} } }} save_jump = {{ __jmpbuf = {0, 0, 0, 0, 0, 0, 0, 0}, __mask_was_saved = 0, __saved_mask = { __val = {0 <repeats 16 times>} } }} tem = XIL(0x7fffffffd130) save = XIL(0x7fffb61b20b5) previous_echo_area_message = XIL(0) also_record = XIL(0) reread = false recorded = false polling_stopped_here = false orig_kboard = 0x555556924ec0 jmpcount = { bytes = 128 } c_volatile = XIL(0) #89 0x000055555577c969 in read_key_sequence (keybuf=0x7fffffffd5d0, prompt=XIL(0), dont_downcase_last=false, can_return_switch_frame=true, fix_current_buffer=true, prevent_redisplay=false, disable_text_conversion_p=false) --Type <RET> for more, q to quit, c to continue without paging-- at ../../emacs/src/keyboard.c:10763 interrupted_kboard = 0x555556924ec0 interrupted_frame = 0x7fffe341bca0 key = XIL(0xd430) used_mouse_menu = false echo_local_start = 0 last_real_key_start = 0 keys_local_start = 0 new_binding = XIL(0x7fffffffd538) count = { bytes = 96 } t = 0 echo_start = 0 keys_start = 0 current_binding = XIL(0x7fff93a23273) first_unbound = 31 mock_input = 0 used_mouse_menu_history = {false <repeats 30 times>} fkey = { parent = XIL(0x7fffe3147cc3), map = XIL(0x7fffe3147cc3), start = 0, end = 0 } keytran = { --Type <RET> for more, q to quit, c to continue without paging-- parent = XIL(0x7fffec00127b), map = XIL(0x7fffec00127b), start = 0, end = 0 } indec = { parent = XIL(0x7fffe3147cab), map = XIL(0x7fffe3147cab), start = 0, end = 0 } shift_translated = false delayed_switch_frame = XIL(0) original_uppercase = XIL(0) original_uppercase_position = -1 disabled_conversion = false starting_buffer = 0x7fffb61b20b0 fake_prefixed_keys = XIL(0) first_event = XIL(0) second_event = XIL(0) #90 0x000055555576522c in command_loop_1 () at ../../emacs/src/keyboard.c:1435 cmd = XIL(0x2aaa95abfe00) keybuf = {XIL(0x12a98), make_fixnum(107), XIL(0x7fffffffd660), XIL(0x55555581ba01), XIL(0x200000038), XIL(0), XIL(0), XIL(0xd158), XIL(0x7fffe3a959e4), XIL(0x7fffe3a959cb), XIL(0x7fffe3a959cb), XIL(0xd158), XIL(0x555555af3f90), XIL(0x7fffe1886988), XIL(0), XIL(0x555556745158), make_fixnum(23456248779936), XIL(0), XIL(0x7fffffffd6f0), XIL(0x55555581c579), XIL(0x7fffe188698d), XIL(0x256dea900), XIL(0), --Type <RET> for more, q to quit, c to continue without paging-- XIL(0xd158), XIL(0x555555af3f90), XIL(0x7fffe15c1c23), XIL(0x7fffe1de517b), XIL(0), XIL(0x7fffffffd730), XIL(0xd158)} i = 1 last_pt = 12041 prev_modiff = 19844 prev_buffer = 0x7fffb61b20b0 #91 0x000055555583e13b in internal_condition_case (bfun=0x555555764dfd <command_loop_1>, handlers=XIL(0xa8), hfun=0x55555576427b <cmd_error>) at ../../emacs/src/eval.c:1618 val = XIL(0x15460) c = 0x7fffe2a52120 #92 0x00005555557649c3 in command_loop_2 (handlers=XIL(0xa8)) at ../../emacs/src/keyboard.c:1174 val = XIL(0x15460) #93 0x000055555583d581 in internal_catch (tag=XIL(0x15460), func=0x555555764999 <command_loop_2>, arg=XIL(0xa8)) at ../../emacs/src/eval.c:1297 val = XIL(0x5555557610c0) c = 0x7fffe2a51fe8 #94 0x0000555555764955 in command_loop () at ../../emacs/src/keyboard.c:1152 #95 0x0000555555763d1d in recursive_edit_1 () at ../../emacs/src/keyboard.c:760 count = { bytes = 32 } val = XIL(0x7fffffffd950) #96 0x0000555555763f49 in Frecursive_edit () at ../../emacs/src/keyboard.c:843 count = { --Type <RET> for more, q to quit, c to continue without paging-- bytes = 0 } buffer = XIL(0) #97 0x000055555575f83e in main (argc=1, argv=0x7fffffffdc08) at ../../emacs/src/emacs.c:2646 stack_bottom_variable = 0x7fffffffda40 old_argc = 1 dump_file = 0x0 no_loadup = false junk = 0x0 dname_arg = 0x0 ch_to_dir = 0x0 original_pwd = 0x0 dump_mode = 0x0 skip_args = 0 temacs = 0x0 attempt_load_pdump = true only_version = false rlim = { rlim_cur = 10022912, rlim_max = 18446744073709551615 } lc_all = 0x0 sockfd = -1 module_assertions = false Lisp Backtrace: --Type <RET> for more, q to quit, c to continue without paging-- 0x93f3e2a0 PVEC_CLOSURE "mapcar" (0xffffa7a0) "let" (0xffffa9f0) "let" (0xffffac00) "reverse" (0xffffad30) "string-join" (0xffffaef0) "mini-echo-concat-segments" (0xffffb020) "let*" (0xffffb320) "if" (0xffffb490) "let*" (0xffffb680) "condition-case" (0xffffb900) "mini-echo-build-info" (0xffffba30) "overlay-put" (0xffffbca0) "let" (0xffffbec0) "while" (0xffffc080) "let" (0xffffc2a0) "if" (0xffffc440) "mini-echo-update" (0xffffc818) "apply" (0xffffc810) "timer-event-handler" (0xffffc9c8) In GNU Emacs 31.0.50 (build 2, x86_64-pc-linux-gnu, X toolkit, cairo version 1.18.2) of 2024-11-25 built on sky Repository revision: fad5e872ca05e45afa42ad5fc77b6890c051e4a6 Repository branch: scratch/igc Windowing system distributor 'The X.Org Foundation', version 11.0.12101014 System Description: Debian GNU/Linux trixie/sid Configured using: 'configure CPPFLAGS=-I/home/oscar/lib/mps/include LDFLAGS=-L/home/oscar/lib/mps/lib --with-native-compilation --with-tree-sitter --without-toolkit-scroll-bars --with-x-toolkit=lucid --with-modules --without-imagemagick --with-mps=yes --enable-checking=yes,glyphs --enable-check-lisp-object-type 'CFLAGS=-O0 -g3'' Configured features: CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GSETTINGS HARFBUZZ JPEG LIBOTF LIBSELINUX LIBXML2 MODULES MPS NATIVE_COMP NOTIFY INOTIFY PDUMPER PNG SECCOMP SOUND SQLITE3 THREADS TIFF TREE_SITTER WEBP X11 XAW3D XDBE XIM XINPUT2 XPM LUCID ZLIB Important settings: value of $LANG: es_ES.UTF-8 locale-coding-system: utf-8-unix Major mode: Lisp Interaction Minor modes in effect: fancy-compilation-mode: t global-git-commit-mode: t pulsar-global-mode: t pulsar-mode: t evil-owl-mode: t evil-paredit-mode: t evil-local-mode: t mini-echo-mode: t global-hide-mode-line-mode: t hide-mode-line-mode: t pdf-occur-global-minor-mode: t TeX-PDF-mode: t key-chord-mode: t paredit-mode: t display-fill-column-indicator-mode: t vertico-multiform-mode: t marginalia-mode: t vertico-mode: t window-highlight-mode: t which-key-mode: t global-anzu-mode: t anzu-mode: t tooltip-mode: t global-eldoc-mode: t eldoc-mode: t show-paren-mode: t electric-indent-mode: t mouse-wheel-mode: t tool-bar-mode: t file-name-shadow-mode: t global-font-lock-mode: t font-lock-mode: t window-divider-mode: t minibuffer-regexp-mode: t column-number-mode: t line-number-mode: t indent-tabs-mode: t auto-composition-mode: t auto-encryption-mode: t auto-compression-mode: t Load-path shadows: /home/oscar/elisp/singles/flx hides /home/oscar/.emacs.d/elpa/flx-20240205.356/flx /home/oscar/elisp/magit/lisp/magit-section hides /home/oscar/.emacs.d/elpa/magit-section-20241122.1431/magit-section /home/oscar/elisp/singles/avy hides /home/oscar/.emacs.d/elpa/avy-20241101.1357/avy /home/oscar/elisp/singles/which-key hides /home/oscar/dev/emacs/emacs/lisp/which-key /home/oscar/elisp/singles/transient hides /home/oscar/dev/emacs/emacs/lisp/transient /home/oscar/.emacs.d/elpa/ef-themes-1.9.0/theme-loaddefs hides /home/oscar/dev/emacs/emacs/lisp/theme-loaddefs Features: (solarized-selenized-dark-theme solarized-palettes solarized solarized-faces company-posframe posframe ispell shadow sort mail-extr emacsbug vertico-directory mule-util fussy meteo-radar flycheck lp0-ts-mode lp0-mode symbol-overlay company-ctags find-file company-fuzzy ht company aggressive-indent deft org-noter org-element org-persist xdg org-id org-element-ast inline avl-tree org-protocol org-capture org-refile org-crypt hl-todo etags-select etags fileloop generator xref fancy-compilation ffap orgit org ob ob-tangle ob-ref ob-lob ob-table ob-exp org-macro org-src sh-script smie executable ob-comint org-pcomplete org-list org-footnote org-faces org-entities noutline outline ob-emacs-lisp ob-core ob-eval org-cycle org-table ol org-fold org-fold-core org-keys oc org-loaddefs org-version org-compat org-macs magit-bookmark git-rebase magit-extras magit-sparse-checkout magit-gitignore magit-ediff ediff magit-subtree magit-patch magit-submodule magit-blame magit-stash magit-reflog magit-bisect magit-push magit-pull magit-fetch magit-clone magit-remote magit-commit magit-sequence magit-notes magit-worktree magit-tag magit-merge magit-branch magit-reset magit-files magit-refs magit-status magit magit-repos magit-apply magit-wip magit-log magit-diff smerge-mode diff git-commit magit-core magit-autorevert autorevert filenotify magit-margin magit-transient magit-process with-editor shell pcomplete magit-mode transient magit-git magit-base which-func vc-git files-x vc-dispatcher magit-section benchmark cursor-sensor pulsar pulse evil-textobj-tree-sitter-core treesit evil-owl buffer-flip evil-paredit evil-anzu evil evil-keybindings evil-integration evil-maps evil-commands evil-digraphs reveal evil-jumps evil-command-window evil-types evil-search evil-ex evil-macros evil-repeat evil-states evil-core evil-common rect evil-vars mini-echo mini-echo-segments hide-mode-line wgrep grep ag vc-svn find-dired s dash pdf-occur ibuf-ext ibuffer ibuffer-loaddefs tablist tablist-filter semantic/wisent/comp semantic/wisent semantic/wisent/wisent semantic/util-modes semantic/util semantic semantic/tag semantic/lex semantic/fw mode-local find-func cedet pdf-isearch let-alist pdf-misc imenu pdf-tools cus-edit cus-load pdf-view bookmark jka-compr pdf-cache pdf-info tq pdf-util format-spec pdf-macs image-mode exif preview reporter desktop frameset latex latex-flymake flymake project compile comint ansi-osc ansi-color tex-ispell tex-style tex dbus xml crm texmathp auctex key-chord comp comp-cstr warnings comp-run comp-common cmake-mode paredit-menu paredit edmacro kmacro server yasnippet lisp-mnt cl-extra help-mode psvn wid-edit log-edit message sendmail yank-media puny rfc822 mml mml-sec epa derived epg rfc6068 epg-config gnus-util text-property-search time-date mm-decode mm-bodies mm-encode mail-parse rfc2231 rfc2047 rfc2045 mm-util ietf-drums mail-prsvr mailabbrev mail-utils gmm-utils mailheader pcvs-util add-log diff-mode track-changes pp elp ediff-merg ediff-mult ediff-wind ediff-diff ediff-help ediff-init ediff-util dired dired-loaddefs display-fill-column-indicator vertico-multiform marginalia vertico flx-rs-core flx-rs flx window-highlight color face-remap nord-theme goto-chg avy rx ring highlight-parentheses ws-butler which-key diminish cl anzu easy-mmode thingatpt tmr pcase compat solar cal-dst cal-menu calendar cal-loaddefs finder-inf advice auctex-autoloads tex-site casual-calc-autoloads casual-lib-autoloads color-theme-sanityinc-tomorrow-autoloads company-posframe-autoloads company-autoloads consult-ag-autoloads consult-flycheck-autoloads consult-lsp-autoloads consult-org-roam-autoloads consult-project-extra-autoloads consult-todo-autoloads deadgrep-autoloads ef-themes-autoloads embark-consult-autoloads consult-autoloads embark-autoloads evil-textobj-tree-sitter-autoloads flutter-autoloads flycheck-autoloads fussy-autoloads flx-autoloads hl-todo-autoloads hotfuzz-autoloads hyperstitional-themes-autoloads lsp-dart-autoloads dart-mode-autoloads dap-mode-autoloads bui-autoloads lsp-docker-autoloads lsp-treemacs-autoloads lsp-ui-autoloads lsp-mode-autoloads f-autoloads marginalia-autoloads markdown-mode-autoloads org-roam-autoloads magit-section-autoloads emacsql-autoloads pdf-tools-autoloads pomm-autoloads alert-autoloads log4e-autoloads gntp-autoloads shackle-autoloads spinner-autoloads symbol-overlay-autoloads tablist-autoloads treemacs-autoloads cfrs-autoloads posframe-autoloads ht-autoloads hydra-autoloads lv-autoloads pfuture-autoloads ace-window-autoloads avy-autoloads s-autoloads info dash-autoloads vertico-autoloads vundo-autoloads wgrep-ag-autoloads wgrep-deadgrep-autoloads wgrep-autoloads yaml-autoloads yeetube-autoloads package browse-url url url-proxy url-privacy url-expand url-methods url-history url-cookie generate-lisp-file url-domsuf url-util mailcap url-handlers url-parse auth-source cl-seq eieio eieio-core cl-macs icons password-cache json subr-x map byte-opt gv bytecomp byte-compile url-vars cl-loaddefs cl-lib rmc iso-transl tooltip cconv eldoc paren electric uniquify ediff-hook vc-hooks lisp-float-type elisp-mode mwheel term/x-win x-win term/common-win x-dnd touch-screen tool-bar dnd fontset image regexp-opt fringe tabulated-list replace newcomment text-mode lisp-mode prog-mode register page tab-bar menu-bar rfn-eshadow isearch easymenu timer select scroll-bar mouse jit-lock font-lock syntax font-core term/tty-colors frame minibuffer nadvice seq simple cl-generic indonesian philippine cham georgian utf-8-lang misc-lang vietnamese tibetan thai tai-viet lao korean japanese eucjp-ms cp51932 hebrew greek romanian slovak czech european ethiopic indian cyrillic chinese composite emoji-zwj charscript charprop case-table epa-hook jka-cmpr-hook help abbrev obarray oclosure cl-preloaded button loaddefs theme-loaddefs faces cus-face macroexp files window text-properties overlay sha1 md5 base64 format env code-pages mule custom widget keymap hashtable-print-readable backquote threads dbusbind inotify dynamic-setting system-font-setting font-render-setting cairo x-toolkit xinput2 x multi-tty move-toolbar make-network-process native-compile mps emacs) Memory information: ((conses 24 0 0) (symbols 56 0 0) (strings 40 0 0) (string-bytes 1 0) (vectors 24 0) (vector-slots 8 0 0) (floats 24 0 0) (intervals 64 0 0) (buffers 1000 0))
bug-gnu-emacs <at> gnu.org
:bug#74547
; Package emacs
.
(Wed, 27 Nov 2024 06:56:01 GMT) Full text and rfc822 format available.Message #8 received at 74547 <at> debbugs.gnu.org (full text, mbox):
From: Gerd Möllmann <gerd.moellmann <at> gmail.com> To: Óscar Fuentes <oscarfv <at> telefonica.net> Cc: 74547 <at> debbugs.gnu.org, Pip Cet <pipcet <at> protonmail.com> Subject: Re: bug#74547: 31.0.50; igc: assertion failed in buffer.c Date: Wed, 27 Nov 2024 07:54:35 +0100
Óscar Fuentes <oscarfv <at> telefonica.net> writes: > While editing a .dart file with lsp-mode. Thanks Oscar. That's a difficult one. > #3 0x00005555559c1384 in mps_lib_assert_fail > (condition=0x555555a4a157 "size > 0", line=579, file=0x555555a47782 "buffer.c") > at /home/oscar/dev/other/mps/code/mpsliban.c:87 > #4 BufferFill > #5 0x00005555559f2da0 in amcSegFix (seg=0x7fffb820d070, ss=0x7fffffff9fc0, refIO=0x7fffffff99d0) > trace = <optimized out> > #6 0x0000555555990b8c in _mps_fix2 (mps_ss=0x7fffffff9fc8, mps_ref_io=0x7fffffff9a10) > res = <optimized out> > #7 0x0000555555903cac in fix_lisp_obj (ss=0x7fffffff9fc8, pobj=0x7fff89f0e000) > at ../../emacs/src/igc.c:998 > res = 32767 > client = 0x7fff93f2f7d0 > base = 0x7fff93f2f7d0 > p = 0x7fff89f0e000 > --Type <RET> for more, q to quit, c to continue without paging-- > word = 140735675561940 > tag = 4 > _ss = 0x7fffffff9fc8 > _mps_zs = 22 > _mps_ufs = 549755846664 > _mps_wt = 32768 > _mps_w = 133143986160 > #8 0x0000555555904160 in fix_array (ss=0x7fffffff9fc8, array=0x7fff89f0e000, n=6) > at ../../emacs/src/igc.c:1233 > res = 30 > i = 0 > _ss = 0x7fffffff9fc8 > _mps_zs = 22 > _mps_ufs = 549755813896 > _mps_wt = <optimized out> > _mps_w = 133143986160 > #9 0x000055555590674b in fix_vectorlike (ss=0x7fffffff9fc8, v=0x7fff89f0dff0) > at ../../emacs/src/igc.c:1974 > res = 32767 > size = 6 > _ss = 0x7fffffff9fc8 > _mps_zs = 22 > _mps_ufs = 549755813896 > _mps_wt = <optimized out> > _mps_w = 133143986160 > #10 0x0000555555908d53 in fix_vector (ss=0x7fffffff9fc8, v=0x7fff89f0dff0) > --Type <RET> for more, q to quit, c to continue without paging-- > at ../../emacs/src/igc.c:2646 > obj_ = 0x7fff89f0dff0 > res = 0 > _ss = 0x7fffffff9fc8 > _mps_zs = 22 > _mps_ufs = 549755813896 > _mps_wt = <optimized out> > _mps_w = 133143986160 > #11 0x00005555559061d4 in dflt_scan_obj > (ss=0x7fffffff9fc8, base_start=0x7fff89f0dff0, > base_limit=0x7fff89f0f000, closure=0x0) I've stripped the rest of the backtrace because it's probably not too relevant. What Emacs is doing here is allocate a cons, which triggers a GC step because the allocation point needs more memory. In this GC step, we scans a memory area containing a vector (or vectorlike) containing 6 elements. The first element is a string for which MPS_FIX1 says it needs to be passed to MPS_FIX2, but MPS_FIX2 aborts. I have no idea why that is. I've added Pip in CC, maybe he has ideas. > In GNU Emacs 31.0.50 (build 2, x86_64-pc-linux-gnu, X toolkit, cairo > version 1.18.2) of 2024-11-25 built on sky > Repository revision: fad5e872ca05e45afa42ad5fc77b6890c051e4a6 > Repository branch: scratch/igc > Windowing system distributor 'The X.Org Foundation', version 11.0.12101014 > System Description: Debian GNU/Linux trixie/sid > > Configured using: > 'configure CPPFLAGS=-I/home/oscar/lib/mps/include > LDFLAGS=-L/home/oscar/lib/mps/lib --with-native-compilation > --with-tree-sitter --without-toolkit-scroll-bars --with-x-toolkit=lucid > --with-modules --without-imagemagick --with-mps=yes > --enable-checking=yes,glyphs --enable-check-lisp-object-type > 'CFLAGS=-O0 -g3'' Could you please configure --with-mps=debug? That uses the debug version of MPS which is more picky, but slower. Also, --enable-checking=igc_debug is probably better. IIRC, that's not on by default, and we probably don't need the other checks. Maybe we some further hints that way.
bug-gnu-emacs <at> gnu.org
:bug#74547
; Package emacs
.
(Sun, 01 Dec 2024 10:51:01 GMT) Full text and rfc822 format available.Message #11 received at 74547 <at> debbugs.gnu.org (full text, mbox):
From: Pip Cet <pipcet <at> protonmail.com> To: Gerd Möllmann <gerd.moellmann <at> gmail.com> Cc: 74547 <at> debbugs.gnu.org, Óscar Fuentes <oscarfv <at> telefonica.net> Subject: Re: bug#74547: 31.0.50; igc: assertion failed in buffer.c Date: Sun, 01 Dec 2024 10:49:57 +0000
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes: > Óscar Fuentes <oscarfv <at> telefonica.net> writes: > >> While editing a .dart file with lsp-mode. > > Thanks Oscar. That's a difficult one. I agree. >> #3 0x00005555559c1384 in mps_lib_assert_fail >> (condition=0x555555a4a157 "size > 0", line=579, file=0x555555a47782 "buffer.c") >> at /home/oscar/dev/other/mps/code/mpsliban.c:87 >> #4 BufferFill >> #5 0x00005555559f2da0 in amcSegFix (seg=0x7fffb820d070, ss=0x7fffffff9fc0, refIO=0x7fffffff99d0) >> trace = <optimized out> >> #6 0x0000555555990b8c in _mps_fix2 (mps_ss=0x7fffffff9fc8, mps_ref_io=0x7fffffff9a10) >> res = <optimized out> >> #7 0x0000555555903cac in fix_lisp_obj (ss=0x7fffffff9fc8, pobj=0x7fff89f0e000) >> at ../../emacs/src/igc.c:998 >> res = 32767 >> client = 0x7fff93f2f7d0 >> base = 0x7fff93f2f7d0 >> p = 0x7fff89f0e000 >> --Type <RET> for more, q to quit, c to continue without paging-- >> word = 140735675561940 >> tag = 4 >> _ss = 0x7fffffff9fc8 >> _mps_zs = 22 >> _mps_ufs = 549755846664 >> _mps_wt = 32768 >> _mps_w = 133143986160 >> #8 0x0000555555904160 in fix_array (ss=0x7fffffff9fc8, array=0x7fff89f0e000, n=6) >> at ../../emacs/src/igc.c:1233 >> res = 30 >> i = 0 >> _ss = 0x7fffffff9fc8 >> _mps_zs = 22 >> _mps_ufs = 549755813896 >> _mps_wt = <optimized out> >> _mps_w = 133143986160 >> #9 0x000055555590674b in fix_vectorlike (ss=0x7fffffff9fc8, v=0x7fff89f0dff0) >> at ../../emacs/src/igc.c:1974 >> res = 32767 >> size = 6 >> _ss = 0x7fffffff9fc8 >> _mps_zs = 22 >> _mps_ufs = 549755813896 >> _mps_wt = <optimized out> >> _mps_w = 133143986160 >> #10 0x0000555555908d53 in fix_vector (ss=0x7fffffff9fc8, v=0x7fff89f0dff0) >> --Type <RET> for more, q to quit, c to continue without paging-- >> at ../../emacs/src/igc.c:2646 >> obj_ = 0x7fff89f0dff0 >> res = 0 >> _ss = 0x7fffffff9fc8 >> _mps_zs = 22 >> _mps_ufs = 549755813896 >> _mps_wt = <optimized out> >> _mps_w = 133143986160 >> #11 0x00005555559061d4 in dflt_scan_obj >> (ss=0x7fffffff9fc8, base_start=0x7fff89f0dff0, >> base_limit=0x7fff89f0f000, closure=0x0) > > I've stripped the rest of the backtrace because it's probably not > too relevant. > > What Emacs is doing here is allocate a cons, which triggers a GC step > because the allocation point needs more memory. In this GC step, we > scans a memory area containing a vector (or vectorlike) containing 6 > elements. The first element is a string for which MPS_FIX1 says it needs > to be passed to MPS_FIX2, but MPS_FIX2 aborts. > > I have no idea why that is. I've added Pip in CC, maybe he has ideas. I think the relevant part is that the IGC header of the object passed to _mps_fix2 is incorrect: it claims to have size 0. This is often the case when no traceable reference to an object was found in a previous GC pass and the memory has been reused for other purposes. So it seems there is a vector or pseudovector of size 6 that somehow attempts to resurrect a freed object (in the first slot). Unfortunately, 6 is the usual size for Lisp closures, so it's a very common allocation and we can't just breakpoint based on that size alone. Do you have a core dump, Óscar? I think we need to look at the vector and see whether we can figure out how it was allocated or modified. I think it's unlikely this particular vector is a closure, FWIW, because the first slot of a closure vector is always a fixnum. Pip
bug-gnu-emacs <at> gnu.org
:bug#74547
; Package emacs
.
(Sun, 01 Dec 2024 12:08:02 GMT) Full text and rfc822 format available.Message #14 received at 74547 <at> debbugs.gnu.org (full text, mbox):
From: Gerd Möllmann <gerd.moellmann <at> gmail.com> To: Pip Cet <pipcet <at> protonmail.com> Cc: 74547 <at> debbugs.gnu.org, Óscar Fuentes <oscarfv <at> telefonica.net> Subject: Re: bug#74547: 31.0.50; igc: assertion failed in buffer.c Date: Sun, 01 Dec 2024 13:05:59 +0100
Pip Cet <pipcet <at> protonmail.com> writes: > I think it's unlikely this particular vector is a closure, FWIW, because > the first slot of a closure vector is always a fixnum. I agree. I've now checked all the possible PVEC types, and the only ones that fit size 6 are normal vectors, closures, or records. I also don't believe that it's a closure because of the fixnum. And records (SQLite) seem a bit unlikely.
bug-gnu-emacs <at> gnu.org
:bug#74547
; Package emacs
.
(Sun, 01 Dec 2024 12:19:01 GMT) Full text and rfc822 format available.Message #17 received at 74547 <at> debbugs.gnu.org (full text, mbox):
From: Gerd Möllmann <gerd.moellmann <at> gmail.com> To: Pip Cet <pipcet <at> protonmail.com> Cc: 74547 <at> debbugs.gnu.org, Óscar Fuentes <oscarfv <at> telefonica.net> Subject: Re: bug#74547: 31.0.50; igc: assertion failed in buffer.c Date: Sun, 01 Dec 2024 13:17:39 +0100
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes: > Pip Cet <pipcet <at> protonmail.com> writes: > >> I think it's unlikely this particular vector is a closure, FWIW, because >> the first slot of a closure vector is always a fixnum. > > I agree. > > I've now checked all the possible PVEC types, and the only ones that fit > size 6 are normal vectors, closures, or records. I also don't believe > that it's a closure because of the fixnum. And records (SQLite) seem a > bit unlikely. Hm, reading Oscar's report again - he was using LSP. Maybe it's something in the parser.
bug-gnu-emacs <at> gnu.org
:bug#74547
; Package emacs
.
(Sun, 01 Dec 2024 12:31:02 GMT) Full text and rfc822 format available.Message #20 received at 74547 <at> debbugs.gnu.org (full text, mbox):
From: Pip Cet <pipcet <at> protonmail.com> To: Gerd Möllmann <gerd.moellmann <at> gmail.com> Cc: 74547 <at> debbugs.gnu.org, Óscar Fuentes <oscarfv <at> telefonica.net> Subject: Re: bug#74547: 31.0.50; igc: assertion failed in buffer.c Date: Sun, 01 Dec 2024 12:30:28 +0000
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes: > Gerd Möllmann <gerd.moellmann <at> gmail.com> writes: >> Pip Cet <pipcet <at> protonmail.com> writes: >> >>> I think it's unlikely this particular vector is a closure, FWIW, because >>> the first slot of a closure vector is always a fixnum. >> >> I agree. >> >> I've now checked all the possible PVEC types, and the only ones that fit >> size 6 are normal vectors, closures, or records. I also don't believe >> that it's a closure because of the fixnum. And records (SQLite) seem a >> bit unlikely. > > Hm, reading Oscar's report again - he was using LSP. Maybe it's > something in the parser. You mean the JSON code? Because I'm just looking at that and it doesn't appear to be protecting its Lisp_Objects at all; but I'm not a hundred percent sure LSP uses the JSON code. In either case, we need to fix json.c, I'll try to do that next. Pip
bug-gnu-emacs <at> gnu.org
:bug#74547
; Package emacs
.
(Sun, 01 Dec 2024 12:41:02 GMT) Full text and rfc822 format available.Message #23 received at 74547 <at> debbugs.gnu.org (full text, mbox):
From: Gerd Möllmann <gerd.moellmann <at> gmail.com> To: Pip Cet <pipcet <at> protonmail.com> Cc: 74547 <at> debbugs.gnu.org, Óscar Fuentes <oscarfv <at> telefonica.net> Subject: Re: bug#74547: 31.0.50; igc: assertion failed in buffer.c Date: Sun, 01 Dec 2024 13:39:09 +0100
Pip Cet <pipcet <at> protonmail.com> writes: > Gerd Möllmann <gerd.moellmann <at> gmail.com> writes: > >> Gerd Möllmann <gerd.moellmann <at> gmail.com> writes: >>> Pip Cet <pipcet <at> protonmail.com> writes: >>> >>>> I think it's unlikely this particular vector is a closure, FWIW, because >>>> the first slot of a closure vector is always a fixnum. >>> >>> I agree. >>> >>> I've now checked all the possible PVEC types, and the only ones that fit >>> size 6 are normal vectors, closures, or records. I also don't believe >>> that it's a closure because of the fixnum. And records (SQLite) seem a >>> bit unlikely. >> >> Hm, reading Oscar's report again - he was using LSP. Maybe it's >> something in the parser. > > You mean the JSON code? Because I'm just looking at that and it doesn't > appear to be protecting its Lisp_Objects at all; but I'm not a hundred > percent sure LSP uses the JSON code. Yes, exactly, json.c. First thing I saw when searching for xfree static void json_parser_done (void *parser) { struct json_parser *p = (struct json_parser *) parser; if (p->object_workspace != p->internal_object_workspace) xfree (p->object_workspace); That at least needs an explanation. I would have expected it to be allocated as root. > > In either case, we need to fix json.c, I'll try to do that next. > > Pip Thanks!
bug-gnu-emacs <at> gnu.org
:bug#74547
; Package emacs
.
(Sun, 01 Dec 2024 12:58:02 GMT) Full text and rfc822 format available.Message #26 received at 74547 <at> debbugs.gnu.org (full text, mbox):
From: Pip Cet <pipcet <at> protonmail.com> To: Gerd Möllmann <gerd.moellmann <at> gmail.com> Cc: 74547 <at> debbugs.gnu.org, Óscar Fuentes <oscarfv <at> telefonica.net>, geza.herman <at> gmail.com Subject: Re: bug#74547: 31.0.50; igc: assertion failed in buffer.c Date: Sun, 01 Dec 2024 12:57:04 +0000
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes: > Pip Cet <pipcet <at> protonmail.com> writes: > Yes, exactly, json.c. First thing I saw when searching for xfree > > static void > json_parser_done (void *parser) > { > struct json_parser *p = (struct json_parser *) parser; > if (p->object_workspace != p->internal_object_workspace) > xfree (p->object_workspace); > > That at least needs an explanation. I would have expected it to be > allocated as root. Well, the explanation is this comment: /* Lisp_Objects are collected in this area during object/array parsing. To avoid allocations, initially internal_object_workspace is used. If it runs out of space then we switch to allocated space. Important note: with this design, GC must not run during JSON parsing, otherwise Lisp_Objects in the workspace may get incorrectly collected. */ Obviously, we cannot make any such guarantees when MPS is in use. (I don't think we can make the guarantee when MPS is not in use, but I'm not totally certain; we certainly allocate strings while parsing JSON, which is sufficient to trigger GC in the MPS case). Note that the json_parser object itself is fine (it's allocated on the stack, thus marked ambiguously), it's only in the case that we create more than 64 Lisp_Object values when parsing a single JSON document that we end up with untraced references on the heap. I don't know whether it's likely that that was what happened to Oscar. My gut feeling is 64 objects would be easily reached by LSP messages, but I'd need more time to test. Anyway, here's a patch which might help: commit c175744f2172ba3405ae98eb3575b2bf4adadfa4 Author: Pip Cet <pipcet <at> protonmail.com> Date: Sun Dec 1 12:46:08 2024 +0000 Ensure JSON parser allocations are traced (bug#74547) * src/json.c (json_parser_done): (json_make_object_workspace_for_slow_path): Use IGC-aware allocations. diff --git a/src/json.c b/src/json.c index eb446f5c221..900fbcbb41a 100644 --- a/src/json.c +++ b/src/json.c @@ -807,7 +807,11 @@ json_parser_done (void *parser) { struct json_parser *p = (struct json_parser *) parser; if (p->object_workspace != p->internal_object_workspace) +#ifdef HAVE_MPS + igc_xfree (p->object_workspace); +#else xfree (p->object_workspace); +#endif if (p->byte_workspace != p->internal_byte_workspace) xfree (p->byte_workspace); } @@ -833,17 +837,31 @@ json_make_object_workspace_for_slow_path (struct json_parser *parser, if (parser->object_workspace_size == JSON_PARSER_INTERNAL_OBJECT_WORKSPACE_SIZE) { +#ifndef HAVE_MPS new_workspace_ptr = xnmalloc (new_workspace_size, sizeof (Lisp_Object)); +#else + new_workspace_ptr + = igc_xalloc_lisp_objs_exact (new_workspace_size); +#endif memcpy (new_workspace_ptr, parser->object_workspace, (sizeof (Lisp_Object) * parser->object_workspace_current)); } else { +#ifndef HAVE_MPS new_workspace_ptr = xnrealloc (parser->object_workspace, new_workspace_size, sizeof (Lisp_Object)); +#else + new_workspace_ptr + = igc_xalloc_lisp_objs_exact (new_workspace_size); + memcpy (new_workspace_ptr, parser->object_workspace, + (sizeof (Lisp_Object) + * parser->object_workspace_current)); + igc_xfree (parser->object_workspace); +#endif } parser->object_workspace = new_workspace_ptr;
bug-gnu-emacs <at> gnu.org
:bug#74547
; Package emacs
.
(Sun, 01 Dec 2024 13:19:02 GMT) Full text and rfc822 format available.Message #29 received at 74547 <at> debbugs.gnu.org (full text, mbox):
From: Óscar Fuentes <oscarfv <at> telefonica.net> To: Gerd Möllmann <gerd.moellmann <at> gmail.com> Cc: Pip Cet <pipcet <at> protonmail.com>, 74547 <at> debbugs.gnu.org Subject: Re: bug#74547: 31.0.50; igc: assertion failed in buffer.c Date: Sun, 01 Dec 2024 14:18:32 +0100
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes: > Hm, reading Oscar's report again - he was using LSP. Maybe it's > something in the parser. The three times that I caugth the crash with the debugger mini-echo [1] was in the Elisp backtrace. Maybe lsp-mode does something that upsets the garbage collector and it surfaces when mini-echo executes. Just now tried for some minutes with mini-echo active and without lsp-mode and no crash, but maybe I was unlucky. lsp-mode is heavy on GC and it is difficult to replicate that. As for the core dump, I have two, but I'm not sure if they contain sensitive info. Usually the crash takes a few minutes of work to happen. I can execute Emacs under gdb on a controlled environment and then answer your requests, no problem with having it open for several days. Or send you the core dump, if it is more useful. 1. https://github.com/liuyinz/mini-echo.el
bug-gnu-emacs <at> gnu.org
:bug#74547
; Package emacs
.
(Sun, 01 Dec 2024 13:32:01 GMT) Full text and rfc822 format available.Message #32 received at 74547 <at> debbugs.gnu.org (full text, mbox):
From: Gerd Möllmann <gerd.moellmann <at> gmail.com> To: Pip Cet <pipcet <at> protonmail.com> Cc: 74547 <at> debbugs.gnu.org, Óscar Fuentes <oscarfv <at> telefonica.net>, geza.herman <at> gmail.com Subject: Re: bug#74547: 31.0.50; igc: assertion failed in buffer.c Date: Sun, 01 Dec 2024 14:30:37 +0100
Pip Cet <pipcet <at> protonmail.com> writes: > Gerd Möllmann <gerd.moellmann <at> gmail.com> writes: >> Pip Cet <pipcet <at> protonmail.com> writes: >> Yes, exactly, json.c. First thing I saw when searching for xfree >> >> static void >> json_parser_done (void *parser) >> { >> struct json_parser *p = (struct json_parser *) parser; >> if (p->object_workspace != p->internal_object_workspace) >> xfree (p->object_workspace); >> >> That at least needs an explanation. I would have expected it to be >> allocated as root. > > Well, the explanation is this comment: > > /* Lisp_Objects are collected in this area during object/array > parsing. To avoid allocations, initially > internal_object_workspace is used. If it runs out of space then > we switch to allocated space. Important note: with this design, > GC must not run during JSON parsing, otherwise Lisp_Objects in > the workspace may get incorrectly collected. */ That explains it, indeed :-(. > > Obviously, we cannot make any such guarantees when MPS is in use. (I > don't think we can make the guarantee when MPS is not in use, but I'm > not totally certain; we certainly allocate strings while parsing JSON, > which is sufficient to trigger GC in the MPS case). If json.c calls something like maybe_quit, which I's expect it must, then GC can indeed happen. See bug#56108 for an example in the regexp code found with ASAN. It's not as risky in the old code as with concurrent GC, but anyway. > > Note that the json_parser object itself is fine (it's allocated on the > stack, thus marked ambiguously), it's only in the case that we create > more than 64 Lisp_Object values when parsing a single JSON document that > we end up with untraced references on the heap. > > I don't know whether it's likely that that was what happened to Oscar. > My gut feeling is 64 objects would be easily reached by LSP messages, > but I'd need more time to test. > > Anyway, here's a patch which might help: > > commit c175744f2172ba3405ae98eb3575b2bf4adadfa4 > Author: Pip Cet <pipcet <at> protonmail.com> > Date: Sun Dec 1 12:46:08 2024 +0000 Very nide, thank you!
bug-gnu-emacs <at> gnu.org
:bug#74547
; Package emacs
.
(Sun, 01 Dec 2024 13:46:01 GMT) Full text and rfc822 format available.Message #35 received at 74547 <at> debbugs.gnu.org (full text, mbox):
From: Gerd Möllmann <gerd.moellmann <at> gmail.com> To: Óscar Fuentes <oscarfv <at> telefonica.net> Cc: Pip Cet <pipcet <at> protonmail.com>, 74547 <at> debbugs.gnu.org Subject: Re: bug#74547: 31.0.50; igc: assertion failed in buffer.c Date: Sun, 01 Dec 2024 14:44:24 +0100
Óscar Fuentes <oscarfv <at> telefonica.net> writes: > Gerd Möllmann <gerd.moellmann <at> gmail.com> writes: > >> Hm, reading Oscar's report again - he was using LSP. Maybe it's >> something in the parser. > > The three times that I caugth the crash with the debugger mini-echo [1] > was in the Elisp backtrace. Maybe lsp-mode does something that upsets > the garbage collector and it surfaces when mini-echo executes. Just now > tried for some minutes with mini-echo active and without lsp-mode and no > crash, but maybe I was unlucky. lsp-mode is heavy on GC and it is > difficult to replicate that. Yeah, It's pretty difficult to find the exact time when something goes wrong because the allocation points have some memory reserved, so that it's not exactly predictable when a GC step happens. But I find Pip's change very promising. It's fixing something that cleqrly cannot work with MPS. Could you please try it (it doesn't seem to be pushed yet.)
bug-gnu-emacs <at> gnu.org
:bug#74547
; Package emacs
.
(Sun, 01 Dec 2024 14:59:02 GMT) Full text and rfc822 format available.Message #38 received at 74547 <at> debbugs.gnu.org (full text, mbox):
From: Pip Cet <pipcet <at> protonmail.com> To: Gerd Möllmann <gerd.moellmann <at> gmail.com> Cc: 74547 <at> debbugs.gnu.org, Óscar Fuentes <oscarfv <at> telefonica.net>, geza.herman <at> gmail.com Subject: Re: bug#74547: 31.0.50; igc: assertion failed in buffer.c Date: Sun, 01 Dec 2024 14:58:10 +0000
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes: > Pip Cet <pipcet <at> protonmail.com> writes: >> Gerd Möllmann <gerd.moellmann <at> gmail.com> writes: >>> Pip Cet <pipcet <at> protonmail.com> writes: >>> Yes, exactly, json.c. First thing I saw when searching for xfree >>> >>> static void >>> json_parser_done (void *parser) >>> { >>> struct json_parser *p = (struct json_parser *) parser; >>> if (p->object_workspace != p->internal_object_workspace) >>> xfree (p->object_workspace); >>> >>> That at least needs an explanation. I would have expected it to be >>> allocated as root. >> >> Well, the explanation is this comment: >> >> /* Lisp_Objects are collected in this area during object/array >> parsing. To avoid allocations, initially >> internal_object_workspace is used. If it runs out of space then >> we switch to allocated space. Important note: with this design, >> GC must not run during JSON parsing, otherwise Lisp_Objects in >> the workspace may get incorrectly collected. */ > > That explains it, indeed :-(. Just to be clear, I think the mixed heap/stack allocation is the right thing to do here, but we need to let both garbage collectors know about the Lisp_Objects we allocated. I think the best way to do that is to use a Lisp_Vector when we run out of stack space. That way, we don't have to worry about forgetting to GC it, and we can use standard functions rather than rolling our own. >> Obviously, we cannot make any such guarantees when MPS is in use. (I >> don't think we can make the guarantee when MPS is not in use, but I'm >> not totally certain; we certainly allocate strings while parsing JSON, >> which is sufficient to trigger GC in the MPS case). > > If json.c calls something like maybe_quit, which I's expect it must, > then GC can indeed happen. See bug#56108 for an example in the regexp > code found with ASAN. It's not as risky in the old code as with > concurrent GC, but anyway. There's a rarely_quit in json_parse_array, which, AFAICS, always triggers in the first loop iteration (when i == 0), but probably never reaches 65536 for the second trigger. My proposal is to modify json.c so it uses a lisp vector if more than 64 objects are needed, and to remove the home-grown symset hash set, replacing it by a standard hash table. Note that the symset is only used to detect duplicate JSON keys. When such duplication is detected, we simply ignore the second plist entry. (I think it would be better to throw an error, but the documentation disagrees.) So here's the patch with the old behavior, where (json-serialize '(a "test" a "ignored")) doesn't throw an error and simply returns "{\"a\":\"test\"}" commit 85fbd342d3b4a8afabe8078e19be9b45fe3e20d2 Author: Pip Cet <pipcet <at> protonmail.com> Date: Sun Dec 1 12:46:08 2024 +0000 Use standard Lisp objects in json.c (bug#74547) * src/json.c (json_out_t): Make the symset table a Lisp_Object. (symset_t): (pop_symset): (cleanup_symset_tables): (symset_hash): (symset_expand): (symset_size): Remove. (make_symset_table): Use an ordinary hash table for the symset. (push_symset): Don't return a value. (symset_add): Use ordinary hash table accessors. (cleanup_json_out): Remove. (json_out_object_cons): Use ordinary hash table for symsets. (json_serialize): (json_parser_init): (json_parser_done): Adjust to use ordinary hash table code. (json_make_object_workspace_for_slow_path): Use an ordinary vector for the workspace. (json_parse_array): Avoid calling rarely_quit(0) (json_parser_done): Remove manual memory management. diff --git a/src/json.c b/src/json.c index eb446f5c221..0e17b893087 100644 --- a/src/json.c +++ b/src/json.c @@ -28,7 +28,6 @@ Copyright (C) 2017-2024 Free Software Foundation, Inc. #include "lisp.h" #include "buffer.h" #include "coding.h" -#include "igc.h" enum json_object_type { @@ -111,161 +110,9 @@ json_parse_args (ptrdiff_t nargs, Lisp_Object *args, ptrdiff_t chars_delta; /* size - {number of characters in buf} */ int maxdepth; - struct symset_tbl *ss_table; /* table used by containing object */ struct json_configuration conf; } json_out_t; -/* Set of symbols. */ -typedef struct -{ - ptrdiff_t count; /* symbols in table */ - int bits; /* log2(table size) */ - struct symset_tbl *table; /* heap-allocated table */ -} symset_t; - -struct symset_tbl -{ - /* Table used by the containing object if any, so that we can free all - tables if an error occurs. */ - struct symset_tbl *up; - /* Table of symbols (2**bits elements), Qunbound where unused. */ - Lisp_Object entries[]; -}; - -static inline ptrdiff_t -symset_size (int bits) -{ - return (ptrdiff_t) 1 << bits; -} - -static struct symset_tbl * -make_symset_table (int bits, struct symset_tbl *up) -{ - int maxbits = min (SIZE_WIDTH - 2 - (word_size < 8 ? 2 : 3), 32); - if (bits > maxbits) - memory_full (PTRDIFF_MAX); /* Will never happen in practice. */ -#ifdef HAVE_MPS - struct symset_tbl *st = igc_xzalloc_ambig (sizeof *st + (sizeof *st->entries << bits)); -#else - struct symset_tbl *st = xmalloc (sizeof *st + (sizeof *st->entries << bits)); -#endif - st->up = up; - ptrdiff_t size = symset_size (bits); - for (ptrdiff_t i = 0; i < size; i++) - st->entries[i] = Qunbound; - return st; -} - -/* Create a new symset to use for a new object. */ -static symset_t -push_symset (json_out_t *jo) -{ - int bits = 4; - struct symset_tbl *tbl = make_symset_table (bits, jo->ss_table); - jo->ss_table = tbl; - return (symset_t){ .count = 0, .bits = bits, .table = tbl }; -} - -/* Destroy the current symset. */ -static void -pop_symset (json_out_t *jo, symset_t *ss) -{ - jo->ss_table = ss->table->up; -#ifdef HAVE_MPS - igc_xfree (ss->table); -#else - xfree (ss->table); -#endif -} - -/* Remove all heap-allocated symset tables, in case an error occurred. */ -static void -cleanup_symset_tables (struct symset_tbl *st) -{ - while (st) - { - struct symset_tbl *up = st->up; -#ifdef HAVE_MPS - igc_xfree (st); -#else - xfree (st); -#endif - st = up; - } -} - -static inline uint32_t -symset_hash (Lisp_Object sym, int bits) -{ - EMACS_UINT hash; -#ifdef HAVE_MPS - hash = igc_hash (sym); -#else - hash = XHASH (sym); -#endif - return knuth_hash (reduce_emacs_uint_to_hash_hash (hash), bits); -} - -/* Enlarge the table used by a symset. */ -static NO_INLINE void -symset_expand (symset_t *ss) -{ - struct symset_tbl *old_table = ss->table; - int oldbits = ss->bits; - ptrdiff_t oldsize = symset_size (oldbits); - int bits = oldbits + 1; - ss->bits = bits; - ss->table = make_symset_table (bits, old_table->up); - /* Move all entries from the old table to the new one. */ - ptrdiff_t mask = symset_size (bits) - 1; - struct symset_tbl *tbl = ss->table; - for (ptrdiff_t i = 0; i < oldsize; i++) - { - Lisp_Object sym = old_table->entries[i]; - if (!BASE_EQ (sym, Qunbound)) - { - ptrdiff_t j = symset_hash (sym, bits); - while (!BASE_EQ (tbl->entries[j], Qunbound)) - j = (j + 1) & mask; - tbl->entries[j] = sym; - } - } -#ifdef HAVE_MPS - igc_xfree (old_table); -#else - xfree (old_table); -#endif -} - -/* If sym is in ss, return false; otherwise add it and return true. - Comparison is done by strict identity. */ -static inline bool -symset_add (json_out_t *jo, symset_t *ss, Lisp_Object sym) -{ - /* Make sure we don't fill more than half of the table. */ - if (ss->count >= (symset_size (ss->bits) >> 1)) - { - symset_expand (ss); - jo->ss_table = ss->table; - } - - struct symset_tbl *tbl = ss->table; - ptrdiff_t mask = symset_size (ss->bits) - 1; - for (ptrdiff_t i = symset_hash (sym, ss->bits); ; i = (i + 1) & mask) - { - Lisp_Object s = tbl->entries[i]; - if (BASE_EQ (s, sym)) - return false; /* Previous occurrence found. */ - if (BASE_EQ (s, Qunbound)) - { - /* Not in set, add it. */ - tbl->entries[i] = sym; - ss->count++; - return true; - } - } -} - static NO_INLINE void json_out_grow_buf (json_out_t *jo, ptrdiff_t bytes) { @@ -283,7 +130,6 @@ cleanup_json_out (void *arg) json_out_t *jo = arg; xfree (jo->buf); jo->buf = NULL; - cleanup_symset_tables (jo->ss_table); } /* Make room for `bytes` more bytes in buffer. */ @@ -442,8 +288,8 @@ json_out_unnest (json_out_t *jo) static void json_out_object_cons (json_out_t *jo, Lisp_Object obj) { + Lisp_Object symset = CALLN (Fmake_hash_table, QCtest, Qeq); json_out_nest (jo); - symset_t ss = push_symset (jo); json_out_byte (jo, '{'); bool is_alist = CONSP (XCAR (obj)); bool first = true; @@ -469,8 +315,9 @@ json_out_object_cons (json_out_t *jo, Lisp_Object obj) key = maybe_remove_pos_from_symbol (key); CHECK_TYPE (BARE_SYMBOL_P (key), Qsymbolp, key); - if (symset_add (jo, &ss, key)) + if (NILP (Fgethash (key, symset, Qnil))) { + Fputhash (key, Qt, symset); if (!first) json_out_byte (jo, ','); first = false; @@ -486,7 +333,6 @@ json_out_object_cons (json_out_t *jo, Lisp_Object obj) } CHECK_LIST_END (tail, obj); json_out_byte (jo, '}'); - pop_symset (jo, &ss); json_out_unnest (jo); } @@ -591,7 +437,6 @@ json_serialize (json_out_t *jo, Lisp_Object object, jo->capacity = 0; jo->chars_delta = 0; jo->buf = NULL; - jo->ss_table = NULL; jo->conf.object_type = json_object_hashtable; jo->conf.array_type = json_array_array; jo->conf.null_object = QCnull; @@ -729,6 +574,7 @@ #define JSON_PARSER_INTERNAL_BYTE_WORKSPACE_SIZE 512 Lisp_Object internal_object_workspace [JSON_PARSER_INTERNAL_OBJECT_WORKSPACE_SIZE]; Lisp_Object *object_workspace; + Lisp_Object object_workspace_vector; size_t object_workspace_size; size_t object_workspace_current; @@ -796,6 +642,7 @@ json_parser_init (struct json_parser *parser, parser->object_workspace_size = JSON_PARSER_INTERNAL_OBJECT_WORKSPACE_SIZE; parser->object_workspace_current = 0; + parser->object_workspace_vector = Qnil; parser->byte_workspace = parser->internal_byte_workspace; parser->byte_workspace_end = (parser->byte_workspace @@ -806,8 +653,6 @@ json_parser_init (struct json_parser *parser, json_parser_done (void *parser) { struct json_parser *p = (struct json_parser *) parser; - if (p->object_workspace != p->internal_object_workspace) - xfree (p->object_workspace); if (p->byte_workspace != p->internal_byte_workspace) xfree (p->byte_workspace); } @@ -818,6 +663,11 @@ json_parser_done (void *parser) json_make_object_workspace_for_slow_path (struct json_parser *parser, size_t size) { + if (NILP (parser->object_workspace_vector)) + { + parser->object_workspace_vector = + Fvector(parser->object_workspace_current, parser->object_workspace); + } size_t needed_workspace_size = (parser->object_workspace_current + size); size_t new_workspace_size = parser->object_workspace_size; @@ -829,23 +679,13 @@ json_make_object_workspace_for_slow_path (struct json_parser *parser, } } - Lisp_Object *new_workspace_ptr; - if (parser->object_workspace_size - == JSON_PARSER_INTERNAL_OBJECT_WORKSPACE_SIZE) - { - new_workspace_ptr - = xnmalloc (new_workspace_size, sizeof (Lisp_Object)); - memcpy (new_workspace_ptr, parser->object_workspace, - (sizeof (Lisp_Object) - * parser->object_workspace_current)); - } - else - { - new_workspace_ptr - = xnrealloc (parser->object_workspace, new_workspace_size, - sizeof (Lisp_Object)); - } + Lisp_Object new_workspace_vector = + larger_vector (parser->object_workspace_vector, + new_workspace_size - parser->object_workspace_size, -1); + + Lisp_Object *new_workspace_ptr = XVECTOR (new_workspace_vector)->contents; + parser->object_workspace_vector = new_workspace_vector; parser->object_workspace = new_workspace_ptr; parser->object_workspace_size = new_workspace_size; } @@ -1476,7 +1316,7 @@ json_parse_array (struct json_parser *parser) result = make_vector (number_of_elements, Qnil); for (size_t i = 0; i < number_of_elements; i++) { - rarely_quit (i); + rarely_quit (~i); ASET (result, i, parser->object_workspace[first + i]); } parser->object_workspace_current = first;
bug-gnu-emacs <at> gnu.org
:bug#74547
; Package emacs
.
(Sun, 01 Dec 2024 15:20:01 GMT) Full text and rfc822 format available.Message #41 received at 74547 <at> debbugs.gnu.org (full text, mbox):
From: Gerd Möllmann <gerd.moellmann <at> gmail.com> To: Pip Cet <pipcet <at> protonmail.com> Cc: 74547 <at> debbugs.gnu.org, Óscar Fuentes <oscarfv <at> telefonica.net>, geza.herman <at> gmail.com Subject: Re: bug#74547: 31.0.50; igc: assertion failed in buffer.c Date: Sun, 01 Dec 2024 16:18:31 +0100
Pip Cet <pipcet <at> protonmail.com> writes: > Gerd Möllmann <gerd.moellmann <at> gmail.com> writes: > >> Pip Cet <pipcet <at> protonmail.com> writes: > >>> Gerd Möllmann <gerd.moellmann <at> gmail.com> writes: >>>> Pip Cet <pipcet <at> protonmail.com> writes: >>>> Yes, exactly, json.c. First thing I saw when searching for xfree >>>> >>>> static void >>>> json_parser_done (void *parser) >>>> { >>>> struct json_parser *p = (struct json_parser *) parser; >>>> if (p->object_workspace != p->internal_object_workspace) >>>> xfree (p->object_workspace); >>>> >>>> That at least needs an explanation. I would have expected it to be >>>> allocated as root. >>> >>> Well, the explanation is this comment: >>> >>> /* Lisp_Objects are collected in this area during object/array >>> parsing. To avoid allocations, initially >>> internal_object_workspace is used. If it runs out of space then >>> we switch to allocated space. Important note: with this design, >>> GC must not run during JSON parsing, otherwise Lisp_Objects in >>> the workspace may get incorrectly collected. */ >> >> That explains it, indeed :-(. > > Just to be clear, I think the mixed heap/stack allocation is the right > thing to do here, but we need to let both garbage collectors know about > the Lisp_Objects we allocated. > > I think the best way to do that is to use a Lisp_Vector when we run out > of stack space. That way, we don't have to worry about forgetting to GC > it, and we can use standard functions rather than rolling our own. Yeah, I'd prefer using Lisp_Vectors too, and it was actually implemented at some point, but removed again, see https://yhetil.org/emacs-devel/87edc1rzig.fsf <at> gmail.com/ I vaguely remember a longer thread about GC in json.c at the time. Could be that that was before igc became a realistic possibility, don't remember. And yes, I've forgotten about it, and should actually have fixed this long ago :-).
bug-gnu-emacs <at> gnu.org
:bug#74547
; Package emacs
.
(Sun, 01 Dec 2024 15:25:01 GMT) Full text and rfc822 format available.Message #44 received at 74547 <at> debbugs.gnu.org (full text, mbox):
From: Eli Zaretskii <eliz <at> gnu.org> To: Pip Cet <pipcet <at> protonmail.com>, Mattias Engdegård <mattiase <at> acm.org>, Géza Herman <geza.herman <at> gmail.com> Cc: gerd.moellmann <at> gmail.com, 74547 <at> debbugs.gnu.org, oscarfv <at> telefonica.net, geza.herman <at> gmail.com Subject: Re: bug#74547: 31.0.50; igc: assertion failed in buffer.c Date: Sun, 01 Dec 2024 17:23:45 +0200
> Cc: 74547 <at> debbugs.gnu.org, > Óscar Fuentes <oscarfv <at> telefonica.net>, geza.herman <at> gmail.com > Date: Sun, 01 Dec 2024 14:58:10 +0000 > From: Pip Cet via "Bug reports for GNU Emacs, > the Swiss army knife of text editors" <bug-gnu-emacs <at> gnu.org> > > Gerd Möllmann <gerd.moellmann <at> gmail.com> writes: > > > Pip Cet <pipcet <at> protonmail.com> writes: > > >> Gerd Möllmann <gerd.moellmann <at> gmail.com> writes: > >>> Pip Cet <pipcet <at> protonmail.com> writes: > >>> Yes, exactly, json.c. First thing I saw when searching for xfree > >>> > >>> static void > >>> json_parser_done (void *parser) > >>> { > >>> struct json_parser *p = (struct json_parser *) parser; > >>> if (p->object_workspace != p->internal_object_workspace) > >>> xfree (p->object_workspace); > >>> > >>> That at least needs an explanation. I would have expected it to be > >>> allocated as root. > >> > >> Well, the explanation is this comment: > >> > >> /* Lisp_Objects are collected in this area during object/array > >> parsing. To avoid allocations, initially > >> internal_object_workspace is used. If it runs out of space then > >> we switch to allocated space. Important note: with this design, > >> GC must not run during JSON parsing, otherwise Lisp_Objects in > >> the workspace may get incorrectly collected. */ > > > > That explains it, indeed :-(. > > Just to be clear, I think the mixed heap/stack allocation is the right > thing to do here, but we need to let both garbage collectors know about > the Lisp_Objects we allocated. > > I think the best way to do that is to use a Lisp_Vector when we run out > of stack space. That way, we don't have to worry about forgetting to GC > it, and we can use standard functions rather than rolling our own. > > >> Obviously, we cannot make any such guarantees when MPS is in use. (I > >> don't think we can make the guarantee when MPS is not in use, but I'm > >> not totally certain; we certainly allocate strings while parsing JSON, > >> which is sufficient to trigger GC in the MPS case). > > > > If json.c calls something like maybe_quit, which I's expect it must, > > then GC can indeed happen. See bug#56108 for an example in the regexp > > code found with ASAN. It's not as risky in the old code as with > > concurrent GC, but anyway. > > There's a rarely_quit in json_parse_array, which, AFAICS, always > triggers in the first loop iteration (when i == 0), but probably never > reaches 65536 for the second trigger. > > My proposal is to modify json.c so it uses a lisp vector if more than 64 > objects are needed, and to remove the home-grown symset hash set, > replacing it by a standard hash table. > > Note that the symset is only used to detect duplicate JSON keys. When > such duplication is detected, we simply ignore the second plist entry. > (I think it would be better to throw an error, but the documentation > disagrees.) > > So here's the patch with the old behavior, where > > (json-serialize '(a "test" a "ignored")) > > doesn't throw an error and simply returns > > "{\"a\":\"test\"}" Adding Mattias and Géza, who were involved in implementing json.c. > commit 85fbd342d3b4a8afabe8078e19be9b45fe3e20d2 > Author: Pip Cet <pipcet <at> protonmail.com> > Date: Sun Dec 1 12:46:08 2024 +0000 > > Use standard Lisp objects in json.c (bug#74547) > > * src/json.c (json_out_t): Make the symset table a Lisp_Object. > (symset_t): > (pop_symset): > (cleanup_symset_tables): > (symset_hash): > (symset_expand): > (symset_size): Remove. > (make_symset_table): Use an ordinary hash table for the symset. > (push_symset): Don't return a value. > (symset_add): Use ordinary hash table accessors. > (cleanup_json_out): Remove. > (json_out_object_cons): Use ordinary hash table for symsets. > (json_serialize): > (json_parser_init): > (json_parser_done): Adjust to use ordinary hash table code. > (json_make_object_workspace_for_slow_path): Use an ordinary vector for > the workspace. > (json_parse_array): Avoid calling rarely_quit(0) > (json_parser_done): Remove manual memory management. > > diff --git a/src/json.c b/src/json.c > index eb446f5c221..0e17b893087 100644 > --- a/src/json.c > +++ b/src/json.c > @@ -28,7 +28,6 @@ Copyright (C) 2017-2024 Free Software Foundation, Inc. > #include "lisp.h" > #include "buffer.h" > #include "coding.h" > -#include "igc.h" > > enum json_object_type > { > @@ -111,161 +110,9 @@ json_parse_args (ptrdiff_t nargs, Lisp_Object *args, > ptrdiff_t chars_delta; /* size - {number of characters in buf} */ > > int maxdepth; > - struct symset_tbl *ss_table; /* table used by containing object */ > struct json_configuration conf; > } json_out_t; > > -/* Set of symbols. */ > -typedef struct > -{ > - ptrdiff_t count; /* symbols in table */ > - int bits; /* log2(table size) */ > - struct symset_tbl *table; /* heap-allocated table */ > -} symset_t; > - > -struct symset_tbl > -{ > - /* Table used by the containing object if any, so that we can free all > - tables if an error occurs. */ > - struct symset_tbl *up; > - /* Table of symbols (2**bits elements), Qunbound where unused. */ > - Lisp_Object entries[]; > -}; > - > -static inline ptrdiff_t > -symset_size (int bits) > -{ > - return (ptrdiff_t) 1 << bits; > -} > - > -static struct symset_tbl * > -make_symset_table (int bits, struct symset_tbl *up) > -{ > - int maxbits = min (SIZE_WIDTH - 2 - (word_size < 8 ? 2 : 3), 32); > - if (bits > maxbits) > - memory_full (PTRDIFF_MAX); /* Will never happen in practice. */ > -#ifdef HAVE_MPS > - struct symset_tbl *st = igc_xzalloc_ambig (sizeof *st + (sizeof *st->entries << bits)); > -#else > - struct symset_tbl *st = xmalloc (sizeof *st + (sizeof *st->entries << bits)); > -#endif > - st->up = up; > - ptrdiff_t size = symset_size (bits); > - for (ptrdiff_t i = 0; i < size; i++) > - st->entries[i] = Qunbound; > - return st; > -} > - > -/* Create a new symset to use for a new object. */ > -static symset_t > -push_symset (json_out_t *jo) > -{ > - int bits = 4; > - struct symset_tbl *tbl = make_symset_table (bits, jo->ss_table); > - jo->ss_table = tbl; > - return (symset_t){ .count = 0, .bits = bits, .table = tbl }; > -} > - > -/* Destroy the current symset. */ > -static void > -pop_symset (json_out_t *jo, symset_t *ss) > -{ > - jo->ss_table = ss->table->up; > -#ifdef HAVE_MPS > - igc_xfree (ss->table); > -#else > - xfree (ss->table); > -#endif > -} > - > -/* Remove all heap-allocated symset tables, in case an error occurred. */ > -static void > -cleanup_symset_tables (struct symset_tbl *st) > -{ > - while (st) > - { > - struct symset_tbl *up = st->up; > -#ifdef HAVE_MPS > - igc_xfree (st); > -#else > - xfree (st); > -#endif > - st = up; > - } > -} > - > -static inline uint32_t > -symset_hash (Lisp_Object sym, int bits) > -{ > - EMACS_UINT hash; > -#ifdef HAVE_MPS > - hash = igc_hash (sym); > -#else > - hash = XHASH (sym); > -#endif > - return knuth_hash (reduce_emacs_uint_to_hash_hash (hash), bits); > -} > - > -/* Enlarge the table used by a symset. */ > -static NO_INLINE void > -symset_expand (symset_t *ss) > -{ > - struct symset_tbl *old_table = ss->table; > - int oldbits = ss->bits; > - ptrdiff_t oldsize = symset_size (oldbits); > - int bits = oldbits + 1; > - ss->bits = bits; > - ss->table = make_symset_table (bits, old_table->up); > - /* Move all entries from the old table to the new one. */ > - ptrdiff_t mask = symset_size (bits) - 1; > - struct symset_tbl *tbl = ss->table; > - for (ptrdiff_t i = 0; i < oldsize; i++) > - { > - Lisp_Object sym = old_table->entries[i]; > - if (!BASE_EQ (sym, Qunbound)) > - { > - ptrdiff_t j = symset_hash (sym, bits); > - while (!BASE_EQ (tbl->entries[j], Qunbound)) > - j = (j + 1) & mask; > - tbl->entries[j] = sym; > - } > - } > -#ifdef HAVE_MPS > - igc_xfree (old_table); > -#else > - xfree (old_table); > -#endif > -} > - > -/* If sym is in ss, return false; otherwise add it and return true. > - Comparison is done by strict identity. */ > -static inline bool > -symset_add (json_out_t *jo, symset_t *ss, Lisp_Object sym) > -{ > - /* Make sure we don't fill more than half of the table. */ > - if (ss->count >= (symset_size (ss->bits) >> 1)) > - { > - symset_expand (ss); > - jo->ss_table = ss->table; > - } > - > - struct symset_tbl *tbl = ss->table; > - ptrdiff_t mask = symset_size (ss->bits) - 1; > - for (ptrdiff_t i = symset_hash (sym, ss->bits); ; i = (i + 1) & mask) > - { > - Lisp_Object s = tbl->entries[i]; > - if (BASE_EQ (s, sym)) > - return false; /* Previous occurrence found. */ > - if (BASE_EQ (s, Qunbound)) > - { > - /* Not in set, add it. */ > - tbl->entries[i] = sym; > - ss->count++; > - return true; > - } > - } > -} > - > static NO_INLINE void > json_out_grow_buf (json_out_t *jo, ptrdiff_t bytes) > { > @@ -283,7 +130,6 @@ cleanup_json_out (void *arg) > json_out_t *jo = arg; > xfree (jo->buf); > jo->buf = NULL; > - cleanup_symset_tables (jo->ss_table); > } > > /* Make room for `bytes` more bytes in buffer. */ > @@ -442,8 +288,8 @@ json_out_unnest (json_out_t *jo) > static void > json_out_object_cons (json_out_t *jo, Lisp_Object obj) > { > + Lisp_Object symset = CALLN (Fmake_hash_table, QCtest, Qeq); > json_out_nest (jo); > - symset_t ss = push_symset (jo); > json_out_byte (jo, '{'); > bool is_alist = CONSP (XCAR (obj)); > bool first = true; > @@ -469,8 +315,9 @@ json_out_object_cons (json_out_t *jo, Lisp_Object obj) > key = maybe_remove_pos_from_symbol (key); > CHECK_TYPE (BARE_SYMBOL_P (key), Qsymbolp, key); > > - if (symset_add (jo, &ss, key)) > + if (NILP (Fgethash (key, symset, Qnil))) > { > + Fputhash (key, Qt, symset); > if (!first) > json_out_byte (jo, ','); > first = false; > @@ -486,7 +333,6 @@ json_out_object_cons (json_out_t *jo, Lisp_Object obj) > } > CHECK_LIST_END (tail, obj); > json_out_byte (jo, '}'); > - pop_symset (jo, &ss); > json_out_unnest (jo); > } > > @@ -591,7 +437,6 @@ json_serialize (json_out_t *jo, Lisp_Object object, > jo->capacity = 0; > jo->chars_delta = 0; > jo->buf = NULL; > - jo->ss_table = NULL; > jo->conf.object_type = json_object_hashtable; > jo->conf.array_type = json_array_array; > jo->conf.null_object = QCnull; > @@ -729,6 +574,7 @@ #define JSON_PARSER_INTERNAL_BYTE_WORKSPACE_SIZE 512 > Lisp_Object internal_object_workspace > [JSON_PARSER_INTERNAL_OBJECT_WORKSPACE_SIZE]; > Lisp_Object *object_workspace; > + Lisp_Object object_workspace_vector; > size_t object_workspace_size; > size_t object_workspace_current; > > @@ -796,6 +642,7 @@ json_parser_init (struct json_parser *parser, > parser->object_workspace_size > = JSON_PARSER_INTERNAL_OBJECT_WORKSPACE_SIZE; > parser->object_workspace_current = 0; > + parser->object_workspace_vector = Qnil; > > parser->byte_workspace = parser->internal_byte_workspace; > parser->byte_workspace_end = (parser->byte_workspace > @@ -806,8 +653,6 @@ json_parser_init (struct json_parser *parser, > json_parser_done (void *parser) > { > struct json_parser *p = (struct json_parser *) parser; > - if (p->object_workspace != p->internal_object_workspace) > - xfree (p->object_workspace); > if (p->byte_workspace != p->internal_byte_workspace) > xfree (p->byte_workspace); > } > @@ -818,6 +663,11 @@ json_parser_done (void *parser) > json_make_object_workspace_for_slow_path (struct json_parser *parser, > size_t size) > { > + if (NILP (parser->object_workspace_vector)) > + { > + parser->object_workspace_vector = > + Fvector(parser->object_workspace_current, parser->object_workspace); > + } > size_t needed_workspace_size > = (parser->object_workspace_current + size); > size_t new_workspace_size = parser->object_workspace_size; > @@ -829,23 +679,13 @@ json_make_object_workspace_for_slow_path (struct json_parser *parser, > } > } > > - Lisp_Object *new_workspace_ptr; > - if (parser->object_workspace_size > - == JSON_PARSER_INTERNAL_OBJECT_WORKSPACE_SIZE) > - { > - new_workspace_ptr > - = xnmalloc (new_workspace_size, sizeof (Lisp_Object)); > - memcpy (new_workspace_ptr, parser->object_workspace, > - (sizeof (Lisp_Object) > - * parser->object_workspace_current)); > - } > - else > - { > - new_workspace_ptr > - = xnrealloc (parser->object_workspace, new_workspace_size, > - sizeof (Lisp_Object)); > - } > + Lisp_Object new_workspace_vector = > + larger_vector (parser->object_workspace_vector, > + new_workspace_size - parser->object_workspace_size, -1); > + > + Lisp_Object *new_workspace_ptr = XVECTOR (new_workspace_vector)->contents; > > + parser->object_workspace_vector = new_workspace_vector; > parser->object_workspace = new_workspace_ptr; > parser->object_workspace_size = new_workspace_size; > } > @@ -1476,7 +1316,7 @@ json_parse_array (struct json_parser *parser) > result = make_vector (number_of_elements, Qnil); > for (size_t i = 0; i < number_of_elements; i++) > { > - rarely_quit (i); > + rarely_quit (~i); > ASET (result, i, parser->object_workspace[first + i]); > } > parser->object_workspace_current = first; > > > > >
bug-gnu-emacs <at> gnu.org
:bug#74547
; Package emacs
.
(Sun, 01 Dec 2024 15:32:01 GMT) Full text and rfc822 format available.Message #47 received at 74547 <at> debbugs.gnu.org (full text, mbox):
From: Óscar Fuentes <oscarfv <at> telefonica.net> To: Pip Cet <pipcet <at> protonmail.com> Cc: Gerd Möllmann <gerd.moellmann <at> gmail.com>, 74547 <at> debbugs.gnu.org, geza.herman <at> gmail.com Subject: Re: bug#74547: 31.0.50; igc: assertion failed in buffer.c Date: Sun, 01 Dec 2024 16:30:49 +0100
Pip Cet <pipcet <at> protonmail.com> writes: > commit 85fbd342d3b4a8afabe8078e19be9b45fe3e20d2 > Author: Pip Cet <pipcet <at> protonmail.com> > Date: Sun Dec 1 12:46:08 2024 +0000 Pip, is that your local repo? Do you intend to push the changes soon or should I apply them as patches over scratch/igc? Today I plan to do quite a lot of work with lsp-mode. Thanks!
bug-gnu-emacs <at> gnu.org
:bug#74547
; Package emacs
.
(Sun, 01 Dec 2024 15:49:02 GMT) Full text and rfc822 format available.Message #50 received at 74547 <at> debbugs.gnu.org (full text, mbox):
From: Pip Cet <pipcet <at> protonmail.com> To: Gerd Möllmann <gerd.moellmann <at> gmail.com> Cc: 74547 <at> debbugs.gnu.org, Óscar Fuentes <oscarfv <at> telefonica.net>, geza.herman <at> gmail.com Subject: Re: bug#74547: 31.0.50; igc: assertion failed in buffer.c Date: Sun, 01 Dec 2024 15:48:21 +0000
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes: > Yeah, I'd prefer using Lisp_Vectors too, and it was actually implemented > at some point, but removed again, see > > https://yhetil.org/emacs-devel/87edc1rzig.fsf <at> gmail.com/ > > I vaguely remember a longer thread about GC in json.c at the time. Could > be that that was before igc became a realistic possibility, don't > remember. Okay, sounds like it's a political issue. I'll push the first patch which keeps changes to a minimum. Pip
bug-gnu-emacs <at> gnu.org
:bug#74547
; Package emacs
.
(Sun, 01 Dec 2024 15:50:02 GMT) Full text and rfc822 format available.Message #53 received at 74547 <at> debbugs.gnu.org (full text, mbox):
From: Gerd Möllmann <gerd.moellmann <at> gmail.com> To: Óscar Fuentes <oscarfv <at> telefonica.net> Cc: Pip Cet <pipcet <at> protonmail.com>, 74547 <at> debbugs.gnu.org, geza.herman <at> gmail.com Subject: Re: bug#74547: 31.0.50; igc: assertion failed in buffer.c Date: Sun, 01 Dec 2024 16:48:23 +0100
Óscar Fuentes <oscarfv <at> telefonica.net> writes: > Pip Cet <pipcet <at> protonmail.com> writes: > >> commit 85fbd342d3b4a8afabe8078e19be9b45fe3e20d2 >> Author: Pip Cet <pipcet <at> protonmail.com> >> Date: Sun Dec 1 12:46:08 2024 +0000 > > Pip, is that your local repo? Do you intend to push the changes soon or > should I apply them as patches over scratch/igc? Today I plan to do > quite a lot of work with lsp-mode. > > Thanks! I think you could apply either patch from Pip, Oscar. They should be functionally equivalent, and it could tell us if we are on the right track. It might take some time until a solution is found (it's Pip's second path :-)) that satisfies all parties.
bug-gnu-emacs <at> gnu.org
:bug#74547
; Package emacs
.
(Sun, 01 Dec 2024 15:56:02 GMT) Full text and rfc822 format available.Message #56 received at 74547 <at> debbugs.gnu.org (full text, mbox):
From: Eli Zaretskii <eliz <at> gnu.org> To: Gerd Möllmann <gerd.moellmann <at> gmail.com> Cc: pipcet <at> protonmail.com, oscarfv <at> telefonica.net, 74547 <at> debbugs.gnu.org, geza.herman <at> gmail.com Subject: Re: bug#74547: 31.0.50; igc: assertion failed in buffer.c Date: Sun, 01 Dec 2024 17:55:04 +0200
> Cc: 74547 <at> debbugs.gnu.org, > Óscar Fuentes <oscarfv <at> telefonica.net>, geza.herman <at> gmail.com > From: Gerd Möllmann <gerd.moellmann <at> gmail.com> > Date: Sun, 01 Dec 2024 16:18:31 +0100 > > Pip Cet <pipcet <at> protonmail.com> writes: > > > Gerd Möllmann <gerd.moellmann <at> gmail.com> writes: > > > >> Pip Cet <pipcet <at> protonmail.com> writes: > > > >>> Gerd Möllmann <gerd.moellmann <at> gmail.com> writes: > >>>> Pip Cet <pipcet <at> protonmail.com> writes: > >>>> Yes, exactly, json.c. First thing I saw when searching for xfree > >>>> > >>>> static void > >>>> json_parser_done (void *parser) > >>>> { > >>>> struct json_parser *p = (struct json_parser *) parser; > >>>> if (p->object_workspace != p->internal_object_workspace) > >>>> xfree (p->object_workspace); > >>>> > >>>> That at least needs an explanation. I would have expected it to be > >>>> allocated as root. > >>> > >>> Well, the explanation is this comment: > >>> > >>> /* Lisp_Objects are collected in this area during object/array > >>> parsing. To avoid allocations, initially > >>> internal_object_workspace is used. If it runs out of space then > >>> we switch to allocated space. Important note: with this design, > >>> GC must not run during JSON parsing, otherwise Lisp_Objects in > >>> the workspace may get incorrectly collected. */ > >> > >> That explains it, indeed :-(. > > > > Just to be clear, I think the mixed heap/stack allocation is the right > > thing to do here, but we need to let both garbage collectors know about > > the Lisp_Objects we allocated. > > > > I think the best way to do that is to use a Lisp_Vector when we run out > > of stack space. That way, we don't have to worry about forgetting to GC > > it, and we can use standard functions rather than rolling our own. > > Yeah, I'd prefer using Lisp_Vectors too, and it was actually implemented > at some point, but removed again, see > > https://yhetil.org/emacs-devel/87edc1rzig.fsf <at> gmail.com/ > > I vaguely remember a longer thread about GC in json.c at the time. Could > be that that was before igc became a realistic possibility, don't > remember. > > And yes, I've forgotten about it, and should actually have fixed this > long ago :-). Please be sure to measure performance. json.c is performance-critical in many applications nowadays, that's why it was implemented in C.
bug-gnu-emacs <at> gnu.org
:bug#74547
; Package emacs
.
(Sun, 01 Dec 2024 15:59:01 GMT) Full text and rfc822 format available.Message #59 received at 74547 <at> debbugs.gnu.org (full text, mbox):
From: Pip Cet <pipcet <at> protonmail.com> To: Óscar Fuentes <oscarfv <at> telefonica.net> Cc: Gerd Möllmann <gerd.moellmann <at> gmail.com>, 74547 <at> debbugs.gnu.org, geza.herman <at> gmail.com Subject: Re: bug#74547: 31.0.50; igc: assertion failed in buffer.c Date: Sun, 01 Dec 2024 15:58:05 +0000
Óscar Fuentes <oscarfv <at> telefonica.net> writes: > Pip Cet <pipcet <at> protonmail.com> writes: > >> commit 85fbd342d3b4a8afabe8078e19be9b45fe3e20d2 >> Author: Pip Cet <pipcet <at> protonmail.com> >> Date: Sun Dec 1 12:46:08 2024 +0000 > > Pip, is that your local repo? Do you intend to push the changes soon or > should I apply them as patches over scratch/igc? Today I plan to do > quite a lot of work with lsp-mode. I've pushed the first patch to scratch/igc. It'd be great if you could run it for a while to see whether it fixes the problem! Thanks! Pip
bug-gnu-emacs <at> gnu.org
:bug#74547
; Package emacs
.
(Sun, 01 Dec 2024 16:25:01 GMT) Full text and rfc822 format available.Message #62 received at 74547 <at> debbugs.gnu.org (full text, mbox):
From: Óscar Fuentes <oscarfv <at> telefonica.net> To: Pip Cet <pipcet <at> protonmail.com> Cc: Gerd Möllmann <gerd.moellmann <at> gmail.com>, 74547 <at> debbugs.gnu.org, geza.herman <at> gmail.com Subject: Re: bug#74547: 31.0.50; igc: assertion failed in buffer.c Date: Sun, 01 Dec 2024 17:24:01 +0100
Pip Cet <pipcet <at> protonmail.com> writes: > Óscar Fuentes <oscarfv <at> telefonica.net> writes: > > I've pushed the first patch to scratch/igc. It'd be great if you could > run it for a while to see whether it fixes the problem! Just built Emacs with the first patch and a long session of work is underway. If Emacs doesn't crash today we can say with certainty that the patch solves the problem... or hides it :-) Thank you.
bug-gnu-emacs <at> gnu.org
:bug#74547
; Package emacs
.
(Sun, 01 Dec 2024 16:34:02 GMT) Full text and rfc822 format available.Message #65 received at 74547 <at> debbugs.gnu.org (full text, mbox):
From: Geza Herman <geza.herman <at> gmail.com> To: Pip Cet <pipcet <at> protonmail.com>, Gerd Möllmann <gerd.moellmann <at> gmail.com> Cc: 74547 <at> debbugs.gnu.org, Óscar Fuentes <oscarfv <at> telefonica.net> Subject: Re: bug#74547: 31.0.50; igc: assertion failed in buffer.c Date: Sun, 1 Dec 2024 17:32:21 +0100
[Message part 1 (text/plain, inline)]
On 12/1/24 16:48, Pip Cet wrote: > Gerd Möllmann<gerd.moellmann <at> gmail.com> writes: > >> Yeah, I'd prefer using Lisp_Vectors too, and it was actually implemented >> at some point, but removed again, see >> >> https://yhetil.org/emacs-devel/87edc1rzig.fsf <at> gmail.com/ >> >> I vaguely remember a longer thread about GC in json.c at the time. Could >> be that that was before igc became a realistic possibility, don't >> remember. > Okay, sounds like it's a political issue. I'll push the first patch > which keeps changes to a minimum. > > Pip > Back then, the future of the new GC was a question, so Gerd said (https://lists.gnu.org/archive/html/emacs-devel/2024-03/msg00544.html) that "Please don't take my GC efforts into consideration. That may succeed or not. But this is also a matter of good design, using the stack, (which BTW pdumper does, too), vs. bad design." That's why we went with the fastest implementation that doesn't use lisp vectors for storage. But we suspected that this JSON parser design will likely cause a problem with the new GC. So I think even if it turned out that the current problem was not caused by the parser, I still think that there should be something done about this JSON parser design to eliminate this potential problem. The lisp vector based approach was reverted because it added an extra pressure to the GC. For large JSON messages, it doesn't matter too much, but when the JSON is small, the extra GC time made the parser measurably slower. But, as far as I remember, that version hadn't have the small internal storage optimization yet. If we convert back to the vector based approach, the extra GC pressure will be smaller (compared to the original vector based approach without the internal storage), as for smaller sizes the vector won't be actually used. Géza
[Message part 2 (text/html, inline)]
bug-gnu-emacs <at> gnu.org
:bug#74547
; Package emacs
.
(Sun, 01 Dec 2024 19:43:01 GMT) Full text and rfc822 format available.Message #68 received at 74547 <at> debbugs.gnu.org (full text, mbox):
From: Gerd Möllmann <gerd.moellmann <at> gmail.com> To: Geza Herman <geza.herman <at> gmail.com> Cc: Pip Cet <pipcet <at> protonmail.com>, Óscar Fuentes <oscarfv <at> telefonica.net>, 74547 <at> debbugs.gnu.org Subject: Re: bug#74547: 31.0.50; igc: assertion failed in buffer.c Date: Sun, 01 Dec 2024 20:41:33 +0100
Geza Herman <geza.herman <at> gmail.com> writes: > On 12/1/24 16:48, Pip Cet wrote: > > Gerd Möllmann <gerd.moellmann <at> gmail.com> writes: > > Yeah, I'd prefer using Lisp_Vectors too, and it was actually implemented > at some point, but removed again, see > > https://yhetil.org/emacs-devel/87edc1rzig.fsf <at> gmail.com/ > > I vaguely remember a longer thread about GC in json.c at the time. Could > be that that was before igc became a realistic possibility, don't > remember. > > > Okay, sounds like it's a political issue. I'll push the first patch > which keeps changes to a minimum. > > Pip > > Back then, the future of the new GC was a question, so Gerd said > (https://lists.gnu.org/archive/html/emacs-devel/2024-03/msg00544.html) that > "Please don't take my GC efforts into consideration. That may succeed or not. But this is also a matter of good design, > using the stack, (which BTW pdumper does, too), vs. bad design." That's why we went with the fastest implementation that > doesn't use lisp vectors for storage. But we suspected that this JSON parser design will likely cause a problem with the > new GC. So I think even if it turned out that the current problem was not caused by the parser, I still think that there > should be something done about this JSON parser design to eliminate this potential problem. The lisp vector based > approach was reverted because it added an extra pressure to the GC. For large JSON messages, it doesn't matter too much, > but when the JSON is small, the extra GC time made the parser measurably slower. But, as far as I remember, that version > hadn't have the small internal storage optimization yet. If we convert back to the vector based approach, the extra GC > pressure will be smaller (compared to the original vector based approach without the internal storage), as for smaller > sizes the vector won't be actually used. > > Géza Sorry again for not remembering this earlier. It only resurfaced slowly in my mind when I saw Pip's patch.
bug-gnu-emacs <at> gnu.org
:bug#74547
; Package emacs
.
(Sun, 01 Dec 2024 21:16:02 GMT) Full text and rfc822 format available.Message #71 received at 74547 <at> debbugs.gnu.org (full text, mbox):
From: Pip Cet <pipcet <at> protonmail.com> To: Geza Herman <geza.herman <at> gmail.com> Cc: Gerd Möllmann <gerd.moellmann <at> gmail.com>, 74547 <at> debbugs.gnu.org, Óscar Fuentes <oscarfv <at> telefonica.net> Subject: Re: bug#74547: 31.0.50; igc: assertion failed in buffer.c Date: Sun, 01 Dec 2024 21:15:41 +0000
"Geza Herman" <geza.herman <at> gmail.com> writes: > On 12/1/24 16:48, Pip Cet wrote: > Gerd M¶llmann <gerd.moellmann <at> gmail.com> writes: > > Back then, the future of the new GC was a question, so Gerd said > (https://lists.gnu.org/archive/html/emacs-devel/2024-03/msg00544.html) > that > "Please don't take my GC efforts into consideration. That may succeed > or not. But this is also a matter of good design, using the stack, > (which BTW pdumper does, too), vs. bad design." That's why we went with > the fastest implementation that doesn't use lisp vectors for storage. > But we suspected that this JSON parser design will likely cause a > problem with the new GC. So I think even if it turned out that the > current problem was not caused by the parser, I still think that there > should be something done about this JSON parser design to eliminate > this potential problem. The lisp vector based approach was reverted > because it added an extra pressure to the GC. For large JSON messages, > it doesn't matter too much, but when the JSON is small, the extra GC > time made the parser measurably slower. But, as far as I remember, that > version hadn't have the small internal storage optimization yet. If we > convert back to the vector based approach, the extra GC pressure will > be smaller (compared to the original vector based approach without the > internal storage), as for smaller sizes the vector won't be actually > used. > G©za Thank you for the summary, that makes sense. Is there a standard corpus of JSON documents that you use to benchmark the code? That would be very helpful, I think, since Eli correctly points out JSON parsing performance is critical. My gut feeling is that we should get rid of the object_workspace entirely, instead modifying the general Lisp code to avoid performance issues (and sacrifice some memory in the process, on most systems). When building a hash table, we can do so directly and fine-tune the hash table code not to reallocate too often. I'd imagine such fine tuning would be generally useful (JSON-derived hash tables are unlikely to exceed the initial 65 elements, but when they do, growing by a factor of four might be appropriate). When building a vector, we might want to introduce a `vtruncate' function which destructively reduces a vector's size without reallocating it. Again, I think that function would be useful in a few other places. Then we could start by allocating a 64-element vector, fill in the array elements, grow it in the rare case that we exceed 64 elements, and truncate it in the common case that fewer than 64 slots are used. No need to copy anything from the stack to the heap, the elements would just appear where they are needed. However, some memory would be wasted, and on low-memory systems, we might want to define `vtruncate' and `hash-table-truncate' to reduce memory usage. Here's some code which might illustrate this idea, but WON'T WORK yet, since the old GC requires vtruncate to do more work. From 9c84c08fd9d4bb9c419025787663b7f7f2611952 Mon Sep 17 00:00:00 2001 From: Pip Cet <pipcet <at> protonmail.com> Date: Sun, 1 Dec 2024 21:00:46 +0000 Subject: [PATCH] Optimize json.c performance * src/alloc.c (Fvtruncate): New function. (syms_of_alloc): Register it. * src/fns.c (Fhash_table_truncate): New function. (syms_of_fns): Register it. * src/json.c (JSON_PARSER_INTERNAL_OBJECT_WORKSPACE_SIZE): Rename to ... (JSON_PARSER_INITIAL_VECTOR_SIZE): ... this. (struct json_parser): Remove object workspace. (json_parser_init): Adjust to removed object workspace. (json_make_object_workspace_for_slow_path, json_make_object_workspace_for): Remove. (json_parse_array): Parse directly to a heap vector, truncate it when done. (json_parse_object): Parse directly to a hash table, truncate it when done. --- src/alloc.c | 25 +++++++++ src/fns.c | 13 +++++ src/json.c | 143 +++++++++++++--------------------------------------- 3 files changed, 74 insertions(+), 107 deletions(-) diff --git a/src/alloc.c b/src/alloc.c index 55126b1d551..b78c27ccf35 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -3935,6 +3935,30 @@ DEFUN ("vector", Fvector, Svector, 0, MANY, 0, return val; } +DEFUN ("vtruncate", Fvtruncate, Svtruncate, 2, 2, 0, + doc: /* Truncate VECTOR so only the first LENGTH elements remain. + +Return a vector to be used instead of VECTOR, which may also be modified +destructively. This function is a performance optimization. */) + (Lisp_Object length, Lisp_Object vector) +{ + CHECK_TYPE (FIXNATP (length), Qwholenump, length); + CHECK_TYPE (VECTORP (vector) && + PSEUDOVECTOR_TYPE (XVECTOR (vector)) == PVEC_NORMAL_VECTOR, + Qvectorp, vector); + if (XFIXNAT (length) > ASIZE (vector)) + signal_error ("vector too short", vector); + if (XFIXNAT (length) == 0) + return zero_vector; + +#ifdef HAVE_MPS + XVECTOR (vector)->header.size = XFIXNAT (length); + return vector; +#else + return Fvector (XFIXNAT (length), XVECTOR (vector)->contents); +#endif +} + DEFUN ("make-byte-code", Fmake_byte_code, Smake_byte_code, 4, MANY, 0, doc: /* Create a byte-code object with specified arguments as elements. The arguments should be the ARGLIST, bytecode-string BYTE-CODE, constant @@ -8600,6 +8624,7 @@ syms_of_alloc (void) defsubr (&Sgarbage_collect_maybe); defsubr (&Smemory_info); defsubr (&Smemory_use_counts); + defsubr (&Svtruncate); #if defined GNU_LINUX && defined __GLIBC__ && \ (__GLIBC__ > 2 || __GLIBC_MINOR__ >= 10) diff --git a/src/fns.c b/src/fns.c index f8191d72443..51bc7488457 100644 --- a/src/fns.c +++ b/src/fns.c @@ -6651,6 +6651,18 @@ DEFUN ("define-hash-table-test", Fdefine_hash_table_test, return Fput (name, Qhash_table_test, list2 (test, hash)); } +DEFUN ("hash-table-truncate", Fhash_table_truncate, + Shash_table_truncate, 1, 1, 0, + doc: /* Indicate that TABLE is unlikely to grow further. + +Returns TABLE, with its internal structures potentially reduced to fit +the current number of elements precisely. This function is a +performance optimization. */) + (Lisp_Object table) +{ + return table; +} + DEFUN ("internal--hash-table-histogram", Finternal__hash_table_histogram, Sinternal__hash_table_histogram, @@ -7408,6 +7420,7 @@ syms_of_fns (void) defsubr (&Shash_table_rehash_threshold); defsubr (&Shash_table_size); defsubr (&Shash_table_test); + defsubr (&Shash_table_truncate); defsubr (&Shash_table_weakness); defsubr (&Shash_table_p); defsubr (&Sclrhash); diff --git a/src/json.c b/src/json.c index 0e17b893087..dd8e45003c4 100644 --- a/src/json.c +++ b/src/json.c @@ -535,7 +535,7 @@ DEFUN ("json-insert", Fjson_insert, Sjson_insert, 1, MANY, } -#define JSON_PARSER_INTERNAL_OBJECT_WORKSPACE_SIZE 64 +#define JSON_PARSER_INITIAL_VECTOR_SIZE 64 #define JSON_PARSER_INTERNAL_BYTE_WORKSPACE_SIZE 512 struct json_parser @@ -565,22 +565,8 @@ #define JSON_PARSER_INTERNAL_BYTE_WORKSPACE_SIZE 512 size_t additional_bytes_count; - /* Lisp_Objects are collected in this area during object/array - parsing. To avoid allocations, initially - internal_object_workspace is used. If it runs out of space then - we switch to allocated space. Important note: with this design, - GC must not run during JSON parsing, otherwise Lisp_Objects in - the workspace may get incorrectly collected. */ - Lisp_Object internal_object_workspace - [JSON_PARSER_INTERNAL_OBJECT_WORKSPACE_SIZE]; - Lisp_Object *object_workspace; - Lisp_Object object_workspace_vector; - size_t object_workspace_size; - size_t object_workspace_current; - - /* String and number parsing uses this workspace. The idea behind - internal_byte_workspace is the same as the idea behind - internal_object_workspace */ + /* String and number parsing uses this workspace. It starts out on + the stack, but moves to the heap if more space is needed. */ unsigned char internal_byte_workspace[JSON_PARSER_INTERNAL_BYTE_WORKSPACE_SIZE]; unsigned char *byte_workspace; @@ -638,12 +624,6 @@ json_parser_init (struct json_parser *parser, parser->additional_bytes_count = 0; - parser->object_workspace = parser->internal_object_workspace; - parser->object_workspace_size - = JSON_PARSER_INTERNAL_OBJECT_WORKSPACE_SIZE; - parser->object_workspace_current = 0; - parser->object_workspace_vector = Qnil; - parser->byte_workspace = parser->internal_byte_workspace; parser->byte_workspace_end = (parser->byte_workspace + JSON_PARSER_INTERNAL_BYTE_WORKSPACE_SIZE); @@ -657,50 +637,6 @@ json_parser_done (void *parser) xfree (p->byte_workspace); } -/* Makes sure that the object_workspace has 'size' available space for - Lisp_Objects */ -NO_INLINE static void -json_make_object_workspace_for_slow_path (struct json_parser *parser, - size_t size) -{ - if (NILP (parser->object_workspace_vector)) - { - parser->object_workspace_vector = - Fvector(parser->object_workspace_current, parser->object_workspace); - } - size_t needed_workspace_size - = (parser->object_workspace_current + size); - size_t new_workspace_size = parser->object_workspace_size; - while (new_workspace_size < needed_workspace_size) - { - if (ckd_mul (&new_workspace_size, new_workspace_size, 2)) - { - json_signal_error (parser, Qjson_out_of_memory); - } - } - - Lisp_Object new_workspace_vector = - larger_vector (parser->object_workspace_vector, - new_workspace_size - parser->object_workspace_size, -1); - - Lisp_Object *new_workspace_ptr = XVECTOR (new_workspace_vector)->contents; - - parser->object_workspace_vector = new_workspace_vector; - parser->object_workspace = new_workspace_ptr; - parser->object_workspace_size = new_workspace_size; -} - -INLINE void -json_make_object_workspace_for (struct json_parser *parser, - size_t size) -{ - if (parser->object_workspace_size - parser->object_workspace_current - < size) - { - json_make_object_workspace_for_slow_path (parser, size); - } -} - static void json_byte_workspace_reset (struct json_parser *parser) { @@ -1258,10 +1194,18 @@ json_parse_number (struct json_parser *parser, int c) json_parse_array (struct json_parser *parser) { int c = json_skip_whitespace (parser); - - const size_t first = parser->object_workspace_current; Lisp_Object result = Qnil; + ptrdiff_t index = 0; + switch (parser->conf.array_type) + { + case json_array_array: + result = make_vector (0, Qnil); + break; + + default: + break; + } if (c != ']') { parser->available_depth--; @@ -1277,10 +1221,15 @@ json_parse_array (struct json_parser *parser) switch (parser->conf.array_type) { case json_array_array: - json_make_object_workspace_for (parser, 1); - parser->object_workspace[parser->object_workspace_current] - = element; - parser->object_workspace_current++; + if (index == ASIZE (result)) + { + ptrdiff_t incr = ASIZE (result); + if (incr == 0) + incr = JSON_PARSER_INITIAL_VECTOR_SIZE; + result = larger_vector (result, incr, -1); + } + ASET (result, index, element); + index++; break; case json_array_list: { @@ -1310,18 +1259,8 @@ json_parse_array (struct json_parser *parser) switch (parser->conf.array_type) { case json_array_array: - { - size_t number_of_elements - = parser->object_workspace_current - first; - result = make_vector (number_of_elements, Qnil); - for (size_t i = 0; i < number_of_elements; i++) - { - rarely_quit (~i); - ASET (result, i, parser->object_workspace[first + i]); - } - parser->object_workspace_current = first; - break; - } + result = Fvtruncate (result, make_fixnum (index)); + break; case json_array_list: break; default: @@ -1349,10 +1288,18 @@ json_parse_object_member_value (struct json_parser *parser) json_parse_object (struct json_parser *parser) { int c = json_skip_whitespace (parser); - - const size_t first = parser->object_workspace_current; Lisp_Object result = Qnil; + switch (parser->conf.object_type) + { + case json_object_hashtable: + result = CALLN (Fmake_hash_table, QCtest, Qequal); + break; + + default: + break; + } + if (c != '}') { parser->available_depth--; @@ -1374,11 +1321,7 @@ json_parse_object (struct json_parser *parser) { Lisp_Object key = json_parse_string (parser, false, false); Lisp_Object value = json_parse_object_member_value (parser); - json_make_object_workspace_for (parser, 2); - parser->object_workspace[parser->object_workspace_current] = key; - parser->object_workspace_current++; - parser->object_workspace[parser->object_workspace_current] = value; - parser->object_workspace_current++; + Fputhash (key, value, result); break; } case json_object_alist: @@ -1426,21 +1369,7 @@ json_parse_object (struct json_parser *parser) { case json_object_hashtable: { - EMACS_INT value = (parser->object_workspace_current - first) / 2; - result = make_hash_table (&hashtest_equal, value, Weak_None, false); - struct Lisp_Hash_Table *h = XHASH_TABLE (result); - for (size_t i = first; i < parser->object_workspace_current; i += 2) - { - hash_hash_t hash; - Lisp_Object key = parser->object_workspace[i]; - Lisp_Object value = parser->object_workspace[i + 1]; - ptrdiff_t i = hash_lookup_get_hash (h, key, &hash); - if (i < 0) - hash_put (h, key, value, hash); - else - set_hash_value_slot (h, i, value); - } - parser->object_workspace_current = first; + result = Fhash_table_truncate (result); break; } case json_object_alist: -- 2.47.0
bug-gnu-emacs <at> gnu.org
:bug#74547
; Package emacs
.
(Wed, 04 Dec 2024 19:13:03 GMT) Full text and rfc822 format available.Message #74 received at 74547 <at> debbugs.gnu.org (full text, mbox):
From: Geza Herman <geza.herman <at> gmail.com> To: Pip Cet <pipcet <at> protonmail.com> Cc: Gerd Möllmann <gerd.moellmann <at> gmail.com>, 74547 <at> debbugs.gnu.org, Óscar Fuentes <oscarfv <at> telefonica.net> Subject: Re: bug#74547: 31.0.50; igc: assertion failed in buffer.c Date: Wed, 4 Dec 2024 20:11:18 +0100
On 12/1/24 22:15, Pip Cet wrote: > "Geza Herman" <geza.herman <at> gmail.com> writes: >> On 12/1/24 16:48, Pip Cet wrote: >> Gerd M¶llmann <gerd.moellmann <at> gmail.com> writes: >> >> Back then, the future of the new GC was a question, so Gerd said >> (https://lists.gnu.org/archive/html/emacs-devel/2024-03/msg00544.html) >> that >> "Please don't take my GC efforts into consideration. That may succeed >> or not. But this is also a matter of good design, using the stack, >> (which BTW pdumper does, too), vs. bad design." That's why we went with >> the fastest implementation that doesn't use lisp vectors for storage. >> But we suspected that this JSON parser design will likely cause a >> problem with the new GC. So I think even if it turned out that the >> current problem was not caused by the parser, I still think that there >> should be something done about this JSON parser design to eliminate >> this potential problem. The lisp vector based approach was reverted >> because it added an extra pressure to the GC. For large JSON messages, >> it doesn't matter too much, but when the JSON is small, the extra GC >> time made the parser measurably slower. But, as far as I remember, that >> version hadn't have the small internal storage optimization yet. If we >> convert back to the vector based approach, the extra GC pressure will >> be smaller (compared to the original vector based approach without the >> internal storage), as for smaller sizes the vector won't be actually >> used. >> G©za > Thank you for the summary, that makes sense. Is there a standard corpus > of JSON documents that you use to benchmark the code? That would be very > helpful, I think, since Eli correctly points out JSON parsing > performance is critical. I'm not aware of such a corpus. When I developed the new JSON parser, the performance difference was so large so it was obvious that the new parser is faster. But I did benchmarks on JSONs which was generated by LSP communication (maybe I can share this one, if there is interest, but I need to anonymize it first), and also I did a benchmark on all the JSONs I found on my computer. But this time, the performance difference is expected to be smaller, using lisp vectors shouldn't have a very large effect on performance. I'd check the performance with small JSONs, but large enough ones where the (non-internal) object_workspace is actually get used (make sure to run a lot of iterations, so the amortized GC time will be included in the result). For larger JSONs, we shouldn't have a difference, as all the other allocations (which store the actual result of the parsing) should hide the additional lisp vector allocation cost. At least, this is my theory. > My gut feeling is that we should get rid of the object_workspace > entirely, instead modifying the general Lisp code to avoid performance > issues (and sacrifice some memory in the process, on most systems). object_workspace is only grown once for the lifetime of one parsing. Once it is grown to the needed size, the only extra cost when parsing a value is to copy the data to its final place from the object_workspace. Truncate based solution does the same copy, but it also needs to grow the hashtable/array for each value, so it executes more allocations and copies than the current solution. So I'd prefer if we kept object_workspace. If the only solution is to convert it to a lisp vector, then I think we should do that. But again, this is just my theory. If we try the truncate based solution, and if it turns out that it's not significantly slower, then it can be a good solution as well.
Óscar Fuentes <oscarfv <at> telefonica.net>
:Óscar Fuentes <oscarfv <at> telefonica.net>
:Message #79 received at 74547-done <at> debbugs.gnu.org (full text, mbox):
From: Óscar Fuentes <oscarfv <at> telefonica.net> To: 74547-done <at> debbugs.gnu.org Cc: Gerd Möllmann <gerd.moellmann <at> gmail.com>, Pip Cet <pipcet <at> protonmail.com>, Geza Herman <geza.herman <at> gmail.com> Subject: Re: bug#74547: 31.0.50; igc: assertion failed in buffer.c Date: Sun, 22 Dec 2024 11:29:24 +0100
After extensive use, I can say with great confidence that this bug is fixed. Closing. Thanks to all.
Debbugs Internal Request <help-debbugs <at> gnu.org>
to internal_control <at> debbugs.gnu.org
.
(Sun, 19 Jan 2025 12:24:09 GMT) Full text and rfc822 format available.
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.