summaryrefslogtreecommitdiffstats
path: root/gc.c
Commit message (Collapse)AuthorAgeFilesLines
* gc: obtain stack top using alloca.Kaz Kylheku2020-01-091-10/+5
| | | | | | | | | | | | | | | | This trick gets rid of the hack for aarch64. If we call alloca, the pointer we get should be below all frame information. Even if for the given target, the compiler-generated code happens to be saving callee-saved registers below the declared variables, any pointer we get from alloca must be below all of that still. * gc.c (STACK_TOP_EXTRA_WORDS): Macro removed. (mark): Don't subtract STACK_TOP_EXTRA_WORDS from gc_stack_top; take the top as-is. (gc): Don't allocate the machine context as an automatic variable; obtain the storage for it from alloca. That then also serves as the stack top.
* gc: consolidate top-of-stack and context handling.Kaz Kylheku2020-01-091-8/+2
| | | | | | | | * gc.c (mark): Eliminate mach_context_t * argument; just gc_stack_top is passed. (gc): Specify the base address of the machine context as the top of the stack. Still, on aarch64, STACK_TOP_EXTRA_WORDS is required, otherwise we get prematurely freed objects.
* aarch64: gc: mark farther beyond apparent stack.Kaz Kylheku2020-01-091-1/+1
| | | | | * gc.c (STACK_TOP_EXTRA_WORDS): Changing from 4 to 12 eliminates crashes.
* Copyright year bump 2020.Kaz Kylheku2019-12-311-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * LICENSE, LICENSE-CYG, METALICENSE, Makefile, alloca.h, args.c, args.h, arith.c, arith.h, buf.c, buf.h, cadr.c, cadr.h, chksum.c, chksum.h, chksums/crc32.c, chksums/crc32.h, combi.c, combi.h, configure, debug.c, debug.h, eval.c, eval.h, ffi.c, ffi.h, filter.c, filter.h, ftw.c, ftw.h, gc.c, gc.h, glob.c, glob.h, hash.c, hash.h, itypes.c, itypes.h, jmp.S, lib.c, lib.h, linenoise/linenoise.c, linenoise/linenoise.h, lisplib.c, lisplib.h, match.c, match.h, parser.c, parser.h, parser.l, parser.y, protsym.c, rand.c, rand.h, regex.c, regex.h, share/txr/stdlib/asm.tl, share/txr/stdlib/awk.tl, share/txr/stdlib/build.tl, share/txr/stdlib/cadr.tl, share/txr/stdlib/compiler.tl, share/txr/stdlib/conv.tl, share/txr/stdlib/debugger.tl, share/txr/stdlib/defset.tl, share/txr/stdlib/doloop.tl, share/txr/stdlib/error.tl, share/txr/stdlib/except.tl, share/txr/stdlib/ffi.tl, share/txr/stdlib/getopts.tl, share/txr/stdlib/getput.tl, share/txr/stdlib/hash.tl, share/txr/stdlib/ifa.tl, share/txr/stdlib/keyparams.tl, share/txr/stdlib/op.tl, share/txr/stdlib/package.tl, share/txr/stdlib/param.tl, share/txr/stdlib/path-test.tl, share/txr/stdlib/place.tl, share/txr/stdlib/pmac.tl, share/txr/stdlib/save-exe.tl, share/txr/stdlib/socket.tl, share/txr/stdlib/stream-wrap.tl, share/txr/stdlib/struct.tl, share/txr/stdlib/tagbody.tl, share/txr/stdlib/termios.tl, share/txr/stdlib/trace.tl, share/txr/stdlib/txr-case.tl, share/txr/stdlib/type.tl, share/txr/stdlib/vm-param.tl, share/txr/stdlib/with-resources.tl, share/txr/stdlib/with-stream.tl, share/txr/stdlib/yield.tl, signal.c, signal.h, socket.c, socket.h, stream.c, stream.h, struct.c, struct.h, strudel.c, strudel.h, sysif.c, sysif.h, syslog.c, syslog.h, termios.c, termios.h, tree.c, tree.h, txr.1, txr.c, txr.h, unwind.c, unwind.h, utf8.c, utf8.h, vm.c, vm.h, vmop.h, win/cleansvg.txr: Extended copyright notices to 2020.
* Move jmp-related stuff from signal.h to unwind.h.Kaz Kylheku2019-12-171-0/+1
| | | | | | | | | | | | | | | | | | * gc.c: Include "unwind.h" for jmp_buf. * signal.h (struct jmp): All versions removed from here. (jmp_save, jmp_restore): Declarations removed from here. (EJ_DBG_MEMB): Macro removed. (extended_jmp_buf): Struct type removed. (extended_setjmp, extended_longjmp): Macros removed. (extjmp_save, extjmp_restore): Declarations removed. * unwind.h (struct jmp): Declared here. (jmp_save, jmp_restore): Declared here. (EJ_DBG_MEMB): Macro moved here. (extended_jmp_buf): Struct type moved here. (extended_setjmp, extended_longjmp): Declared here. (extjmp_save, extjmp_restore): Declared here.
* gc: bugfix: maintain tail pointer in new sweep code.Kaz Kylheku2019-11-091-3/+2
| | | | | | | | | * gc.c (sweep): The new logic for removing a deleted heap's blocks from the free list must correctly maintain free_tail. Whenever a node is deleted which is the tail node, the tail pointer must move to the parent's tail field, or to the free_list pointer. We don't need to do anything afterward for the free_list == 0 case; that is taken care of.
* gc: recalculate heap bounding box when sweeping.Kaz Kylheku2019-11-081-0/+7
| | | | | | | | | | Since sweep can delete heaps now, it's possible that the bounding box may be tightened. Since we are iterating over all heaps, we can just recalculate it. * gc.c (sweep): Recalculate the heap boundaries using local variables, taking care to exclude any heap that is being deleted. Then update the globals.
* gc: free heaps that become empty.Kaz Kylheku2019-11-081-2/+41
| | | | | | | | | | | | | | | | | On glibc, our heap allocation requests are considered large and handled via mmap; when we free a heap, the memory is returned to the OS via munmap. * gc.c (sweep): If every object in a heap is freed, we free the entire heap, taking care to also reset the free list to the state before those objects were added to it. The free list may still contain objects from that same heap that were not just added to it (they were freed in a previous GC pass), so we must walk the free list to find the remaining objects and remove them. The Valgrind debugging logic (opening access and closing while walking the list) was too cumbersome so it's done in two passes: open access to the whole free list, process it, close off what is left.
* New data type: tnode.Kaz Kylheku2019-09-221-0/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Binary search tree nodes are being added as a basic heap data type. The C type tag is TNOD, and the Lisp type is tnode. Binary search tree nodes have three elements: a key, a left child and a right child. The printed notation is #N(key left right). Quasiquoting is supported: ^#N(,foo ,bar) but not splicing. Because tnodes have three elements, they they fit into TXR's four-word heap cell, not requiring any additional memory allocation. These nodes are going to be the basis for a binary search tree container, which will use the scapegoat tree algorithm for maintaining balance. * tree.c, tree.h: New files. * Makefile (OBJS): Adding tree.o. * eval.c (expand_qquote_rec): Recurse through tnode cells, so unquotes work inside #N syntax. * gc.c (finalize): Add TNOD to no-op case in switch; tnodes don't require finalization. (mark_obj): Traverse tnode cell. * hash.c (equal_hash): Add TNOD case. * lib.c (tnode_s): New symbol variable. (seq_kind_tab): New entry for TNOD, mapping to SEQ_NOTSEQ. (code2type, equal): Handle TNOD. (obj_init): Initialize tnode_s variable. (obj_print_impl, populate_obj_hash): Handle TNOD. (init): Call tree_init function in tree.c. * lib.h (enum type, type_t): New enumeration TNOD. (struct tnod): New struct type. (union obj, obj_t): New union member tn of type struct tnod. (tnode_s): Declard. * parserc.c (circ_backpatch): Handle TNOD, so circular notation works through tnode cells. * parser.l (grammar): Recognize #N prefix, mapping to HASH_N token. * parser.y (HASH_N): New grammar terminal symbol. (tnode): New nonterminal symbol. (i_expr, n_expr): Add tnode cases to productions. (yybadtoken): Map HASH_N to "#N" string.
* gc: align objects more strictly.Kaz Kylheku2019-09-121-3/+18
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In this commit, we ensure that objects in the heap are aligned to at east eight byte boundaries (the minimum alignment from most malloc implementations on 32 and 64 bit systems). If possible, we align objects to a multiple of their size, sizeof (obj_t), which is 16 bytes on 32 bit platforms and 32 bytes on 64 bit platforms. We do this by making the object array the first field of the heap structure, and by allocating it with an aligned allocator function, if possible. * configure: detect memory alignment function: either memalign (preferred) or else posix_memalign (ugly duckling). We conditionally add either HAVE_MEMALIGN or HAVE_POSIX_MEMALIGN into config.h. * gc.c (OBJ_ALIGN): New macro. (struct heap, heap_t): Put the block member first, so objects are aligned with the containing heap. (in_heap): If the pointer is not aligned to a multiple of OBJ_ALIGN, it can't be a heap object; return zero. If allocations of the heap are aligned, then we don't need the additional alignment check in the loop body; if the pointer lands in the array, then the earlier OBJ_ALIGN check assures us it must be aligned. If we have only malloc alignment, we must do the check; the pointer could be to an address divisible by 8 which is in the middle of an obj_t. * lib.c: If HAVE_MEMALIGN is true, then include <malloc.h> so we have it declared. (memalign): If HAVE_POSIX_MEMALIGN is true, this static function is defined; it's compatible with the Glibc memalign. If HAVE_MEMALIGN and HAVE_POSIX_MEMALIGN are false, then memalign is defined as a malloc wrapper which doesn't align. (chk_malloc_gc_more): Use memalign instead of malloc. If aligned allocation is available, this will cause the heap to be aligned to a multiple of the object size.
* gc: bug in determining tight heap bounding box.Kaz Kylheku2019-09-121-2/+2
| | | | | | | | * gc.c (more): The heap_max_bound and heap_min_bound variables are initialized to null. We must update them unconditionally if they are in that state. What's happening otherwise is that heap_min_bound stays null and so we unnecessarily process false positives in the in_heap function.
* gc: remove #if 0 and #if 1.Kaz Kylheku2019-08-121-8/+0
| | | | | * gc.c (mark_obj): Remove material excluded by #if 1. (gc): Eliminate #if 0 block.
* sha256: recycle I/O buffer used in stream hash.Kaz Kylheku2019-07-041-0/+1
| | | | | | | | | | | | | * chksum.c (sha256_stream): Use iobuf_get and iobuf_put. * gc.c (gc): Do not mark the list of recycled buffers; just consider them to be garbage and clear the list, like we do with recycled conses via rcyc_empty. * stream.c (iobuf_free_list): New static variable. (iobuf_get, iobuf_put, iobuf_list_empty): New functions. * stream.h (iobuf_get, iobuf_put, iobuf_list_empty): Declared.
* internal debug support: reduce noise from sweep_one.Kaz Kylheku2019-06-191-1/+1
| | | | | | | | * gc.c (sweep_one): If the swept object matches the break_obj, only log it if the object isn't free. Otherwise if break_obj is sitting on the free list, we will uselessly report on it on every sweep operation, which is very often under --gc-debug torture operation.
* gc: bug: finalized objects not reclaimed.Kaz Kylheku2019-02-181-1/+11
| | | | | | | | | | | | | | | | | The problem: in an incremental GC run, when an generation 0 object is determined to be unreachable and has a registered finalizer, it ends up hanging around until a full GC. This is because it is marked as if it were reachable (just in case the finalizer re-introduces it into the object graph) and left to be processed at the next GC. However, what's missing is that the object is not in the freshobj array any more, and so it is not reclaimed by the sweep function. Effectively, it's as if the object had been promoted to gen 1. * gc.c (call_finalizers_impl): After invoking a finalizer, if the object is still in gen 0, add it to the freshobj array as if it had just been allocated. If there is no room in the freshobj array, set the full_gc flag, as usual.
* Copyright year bump 2019.Kaz Kylheku2019-01-161-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * LICENSE, LICENSE-CYG, METALICENSE, Makefile, args.c, args.h, arith.c, arith.h, buf.c, buf.h, cadr.c, cadr.h, combi.c, combi.h, configure, debug.c, debug.h, eval.c, eval.h, ffi.c, ffi.h, filter.c, filter.h, ftw.h, gc.c, gc.h, glob.c, glob.h, hash.c, hash.h, itypes.c, itypes.h, jmp.S, lib.c, lib.h, lisplib.c, lisplib.h, match.c, match.h, parser.c, parser.h, parser.l, parser.y, protsym.c, rand.c, rand.h, regex.c, regex.h, share/txr/stdlib/asm.tl, share/txr/stdlib/awk.tl, share/txr/stdlib/build.tl, share/txr/stdlib/cadr.tl, share/txr/stdlib/compiler.tl, share/txr/stdlib/conv.tl, share/txr/stdlib/doloop.tl, share/txr/stdlib/error.tl, share/txr/stdlib/except.tl, share/txr/stdlib/ffi.tl, share/txr/stdlib/getopts.tl, share/txr/stdlib/getput.tl, share/txr/stdlib/hash.tl, share/txr/stdlib/ifa.tl, share/txr/stdlib/keyparams.tl, share/txr/stdlib/op.tl, share/txr/stdlib/package.tl, share/txr/stdlib/path-test.tl, share/txr/stdlib/place.tl, share/txr/stdlib/pmac.tl, share/txr/stdlib/socket.tl, share/txr/stdlib/stream-wrap.tl, share/txr/stdlib/struct.tl, share/txr/stdlib/tagbody.tl, share/txr/stdlib/termios.tl, share/txr/stdlib/trace.tl, share/txr/stdlib/txr-case.tl, share/txr/stdlib/type.tl, share/txr/stdlib/vm-param.tl, share/txr/stdlib/with-resources.tl, share/txr/stdlib/with-stream.tl, share/txr/stdlib/yield.tl, signal.c, signal.h, socket.c, socket.h, stream.c, stream.h, struct.c, struct.h, strudel.c, strudel.h, sysif.c, sysif.h, syslog.c, syslog.h, termios.c, termios.h, txr.1, txr.c, txr.h, unwind.c, unwind.h, utf8.c, utf8.h, vm.c, vm.h, vmop.h, win/cleansvg.txr: Extended Copyright line to 2018.
* Drastically reduce inclusion of <dirent.h>.Kaz Kylheku2018-12-111-1/+0
| | | | | | | | | | | | | | | | | | | The <dirent.h> header is included all over the place because it is needed by a single declaration in stream.h. That declaration is for a function that is only called within stream.c, so we make it internal. Now only stream.c has to include <dirent.h>. * buf.c, debug.c, eval.c, ffi.c, filter.c, gc.c, gencadr.txr, hash.c, lib.c, lisplib.c, match.c, parser.c, regex.c, socket.c, struct.c, strudel.c, sysif.c, syslog.c, termios.c, txr.c, unwind.c, vm.c: Remove #include <dirent.h>. * cadr.c: Regenerated. * stream.c (make_dir_stream): Make external function static. * stream.h (make_dir_stream): Declaration updated.
* type_check: take function name arg.Kaz Kylheku2018-11-071-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * arith.c (flo_int): Pass down name to type_check. * eval.c (copy_env, env_fbind, env_vbind, env_vb_to_fb, func_get_name, lexical_var_p, lexical_fun_p, lexical_lisp1_binding, squash_menv_deleting_range, op_upenv): Pass relevant Lisp function name to type_check. (lookup_global_var, lookup_sym_lisp1, lookup_fun, lookup_mac, lookup_symac, lookup_symac_lisp1): For these widely used functions, pass situational prefix in place of function name. They may get a funtion name argument in the future. * gc.c (gc_finalize): Pass function name to type_check. * lib.c (throw_mismatch): Take function nme argument, incorporate into mesage. (lcons_fun, c_flo, string_extend, symbol_name, symbol_package, get_package, package_name, func_get_form, func_get_env, func_set_env, vec_set_length, length_vec, size_vec, list_vec, lay_str_force, lay_str_force_upto, lazy_str_get_trailing_list, from, too, set_from, set_to): Pass relevant Lisp function name to type_check. (symbol_setname, symbol_visible): Pass indication of internal error into type_check, since this doesn't pertain to any Lisp function being wrong. * lib.h (throw_mismatch): Declaration updated. (type_check): Take new parameter and pass down to throw_mismatch. * signal.c (set_sig_handler): Pass name down to type_check.
* gc: eliminate most uses of gc_mutated.Kaz Kylheku2018-11-061-9/+10
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The code is using gc_mutated in situations that resemble assignment: a value is stored into a slot in some object. These situations should be handled using the same logic as embodied in the gc_set function. This is because gc_set will consider both objects, and in many cases will not have to do anything special. E.g. if an immature object is stored into another immature object, or mature into immature, or mature into mature. Whereas gc_mutated is a "just in case" function which forces the garbage collector to traverse the indicated object, if that object is mature. In this patch we refactor gc_set to expose its underlying logic with a somewhat more flexible function called gc_assign_check. We put that behind a conditionally defined macro called setcheck, and then use that to replace invocations of the mut macro in various places. The only uses of gc_mutated that remain are in the bulk vector assignment and copy_struct: operations in which potentially many element values are migrated from one aggregate object to another, making it potentially expensive to do individual assignment checks. * gc.c (gc_assign_check): New function, formed from guts of gc_set. (gc_set): Now a trivial function, implemented via call to gc_assign_check. * gc.h (gc_assign_check): Declared. * lib.c (cons): Use setcheck instead of gc_mutated, since we are storing only two values into the existing cons: the car and the cdr. * struct.c (clear_struct): Use setcheck instead of gc_mutated, since we are just storing one value into the structure, the clear_val. The fact that we are storing it into multiple slots is irrelevant. * vm.c (vm_make_closure): Use setcheck instead of mut, using the new heap_vector as the child object with regard to the closure. Rationale: the only threat here is that when we allocate the heap vector, a GC is triggered which pushes the closure into the mature generation. Then the store of the heap vector into the closure is a wrong-way reference, with regard to generational GC. The elements in the vector are immaterial; they are older than both the closure and the vector, therefore their relationship to either object is a right-way reference. (vm_set, vm_sm_set): Replace mut by a setcheck between the vector from the display and the new value being stored in it. (vm_stab): Replace the gc_mutated check, which should have been a mut macro call, with a setcheck between the vm, and the binding being stored into the table. The gc_mutated should have been wrapped with an #if CONFIG_GEN_GC so we are fixing a build bug here: the code would have prevented TXR from being built with the generational GC disabled.
* gc: tail recurse on env rather than code.Kaz Kylheku2018-03-201-4/+5
| | | | | | | * gc.c (mark_obj): When marking functions, tail recurse on the environment. That's the pointer more likely to be a gateway to serious depth, rather than the vm description or interpreted function's source.
* vm: handle FVM function type thorughout run-time.Kaz Kylheku2018-03-161-1/+5
| | | | | | | | | | | | | | | | * gc.c (mark_obj): Recognize FVM functions and mark their vm_desc. * lib.c (equal): Handle equality for FVM. If the environment pointers are equal, consider the functions equal. (funcall, funcall1, funcall2, funcall3, funcall4): Recognize and call FVM functions. However, there is a lack of robustness here that needs to be addressed: vm_execute_closure doesn't check whether there are too many or not enough arguments. Interpreted functions have a run-time check inside bind_args. (obj_print_impl): Don't print VM functions as #<intrinsic fun...> but rather #<vm fun>.
* Copyright year bump 2018.Kaz Kylheku2018-02-151-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * LICENSE, LICENSE-CYG, METALICENSE, Makefile, args.c, args.h, arith.c, arith.h, buf.c, buf.h, cadr.c, cadr.h, combi.c, combi.h, configure, debug.c, debug.h, eval.c, eval.h, ffi.c, ffi.h, filter.c, filter.h, ftw.c, ftw.h, gc.c, gc.h, glob.c, glob.h, hash.c, hash.h, itypes.c, itypes.h, jmp.S, lib.c, lib.h, lisplib.c, lisplib.h, match.c, match.h, parser.c, parser.h, parser.l, parser.y, protsym.c, rand.c, rand.h, regex.c, regex.h, share/txr/stdlib/awk.tl, share/txr/stdlib/build.tl, share/txr/stdlib/cadr.tl, share/txr/stdlib/conv.tl, share/txr/stdlib/doloop.tl, share/txr/stdlib/error.tl, share/txr/stdlib/except.tl, share/txr/stdlib/ffi.tl, share/txr/stdlib/getopts.tl, share/txr/stdlib/getput.tl, share/txr/stdlib/hash.tl, share/txr/stdlib/ifa.tl, share/txr/stdlib/keyparams.tl, share/txr/stdlib/op.tl, share/txr/stdlib/package.tl, share/txr/stdlib/path-test.tl, share/txr/stdlib/place.tl, share/txr/stdlib/pmac.tl, share/txr/stdlib/socket.tl, share/txr/stdlib/stream-wrap.tl, share/txr/stdlib/struct.tl, share/txr/stdlib/tagbody.tl, share/txr/stdlib/termios.tl, share/txr/stdlib/txr-case.tl, share/txr/stdlib/type.tl, share/txr/stdlib/with-resources.tl, share/txr/stdlib/with-stream.tl, share/txr/stdlib/yield.tl, signal.c, signal.h, socket.c, socket.h, stream.c, stream.h, struct.c, struct.h, strudel.c, strudel.h, sysif.c, sysif.h, syslog.c, syslog.h, termios.c, termios.h, txr.1, txr.c, txr.h, unwind.c, unwind.h, utf8.c, utf8.h, win/cleansvg.txr: Extended Copyright line to 2018.
* Port to aarch64 (ARM 8).Kaz Kylheku2017-08-161-1/+7
| | | | | | | | | | | | Continuations don't work yet. * gc.c (STACK_TOP_EXTRA_WORDS): New macro. (mark): On aarch64, we must include four words above the stack top. Some live root pointers sometimes hide there which are not in any of the callee-saved register that end up in the machine context via jmp_save. * jmp.S (jmp_save, jmp_restore): Implement for aarch64.
* gc: remove assertion from make_obj.Kaz Kylheku2017-07-191-1/+0
| | | | | | | * gc.c (make_obj): remove assertion that the object pulled from the free list is marked FREE. This hasn't proved to be valuable and adds a nonzero cost to a frequently executed path.
* ffi: sanity check on object in ffi_val_get.Kaz Kylheku2017-05-241-0/+14
| | | | | | | | | | | | | | | | | * ffi.c (ffi_val_get): Throw an exception if the object doesn't appear valid. * gc.c (valid_object_p): New function. Invalid objects are those that are pointers, but either not into a heap, or else to a freed object or to an object that is marked by the garbage collector (should only be seen while GC is running). All others are valid. There can be false positives here: a value with the LIT tag is in fact a pointer, but we don't check whether that is valid. * gc.c (valid_object_p): Declared. * txr.1: Remarks added to documentation of FFI val type.
* Splitting cptr object into separate CPTR tag.Kaz Kylheku2017-05-151-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | CPTR shares representation and a lot of implementation with COBJ. The COBJ class symbol is the CPTR type tag. There is no hierarchy among CPTR tags. The nil tag is used for a modicum of type looseness, so that we don't straitjacket ourselves too much into this tag-based typing scheme. All existing cptr objects are becoming CPTR, and all get a nil tag, except for dlopen library handles, and dlsym symbols, which are tagged as dlhandle and dlsym. The FFI framework will support tag-declared cptr's. This will help with safety. For instance, suppose an API has half a dozen different kinds of opaque handles. If they are all just cptr on the TXR Lisp side, it's easy to mix them up, passing the wrong one to the wrong C function. * lib.h (enum type): New enum member, CPTR. (cptr_print_op, cptr_typed, cptrp, cptr_type, cptr_handle): Declared. (cptr_addr_of): Parameters added. * lib.c (code2type): Map CPTR type code to cptr_s. (equal): Handle CPTR objects. They are only equal to other CPTR objects which have the same operations, and are equal under the equal function of those operations. (cptr_print_op): New function. (cptr_ops): Use cptr_print_op rather than cobj_print_op. (cptr_typed): New function. (cptr): Use cptr_typed to make a cptr with tag nil, rather than using cobj. (cptrp, cptr_handle, cptr_type): New functions. (cptr_get): Go through cptr_handle rather than cobj_handle. (cptr_addr_of, cptr_zap, cptr_free): Use call to cptr_handle rather than cobj_handle for the type checking side effect. New parameters for type and parent function name. (obj_print_impl): Handle CPTR with same case as COBJ. * gc.c (finalize, mark_obj): Handle CPTR cases using common code with COBJ. * hash.c (equal_hash): Handle CPTR just like COBJ. * eval.c (eval_init): Register cptrp and cptr-type intrinsic functions. * ffi.c (ffi_cptr_put, ffi_cptr_get, ffi_cptr_alloc): Use the potentially type-safe cptr_handle, instead of cptr_get. However, for an untagged cptr, there is no type safety because tft->mtypes is nil. The argument can be any kind of cptr. * sysif.c (dlhandle_s, dlsym_s): New symbol variables. (cptr_dl_ops): Use cptr_print_op. (dlopen_wrap, dlclose_wrap): Use typed cptr with dlhandle as the type. (dlsym_wrap, dlsym_checked, dlvsym_wrap, dlvsym_checked): Recognize only a cptr of type dlhandle for the library. Construct a typed cptr of type dlsym. (sysif_init): Initialize dlhandle_s and dlsym_s. Register dlsym function using dlsym_s.
* gc: bug in --free-all --vg-debug combination.Kaz Kylheku2017-05-131-1/+1
| | | | | | | | * gc.c (gc_free_all): Mark defined the current block being iterated, not the next one. Otherwise Valgrind generates numerous false errors from accesses to free objects in the first block. Not to mention that next is a null pointer in the last iteration.
* gc: use symbolic constants for special vec slots.Kaz Kylheku2017-05-121-4/+4
| | | | | | | * gc.c (mark_obj): The vector alloc size and length which lie at negative indices should be accessed using the index constants vec_alloc and vec_length, rather than -2 and -1.
* New buffer data type.Kaz Kylheku2017-04-161-1/+10
| | | | | | | | | | | | | | | | | | | | | | | Work in progress. * gc.c (finalize): Add cast to switch expression so gcc flags when we are missing one of the enumerations. Handle new BUF enum to free dynamic buffers. (mark_obj): Mark len and size fields of buf, in case they aren't just nil or integers. * hash.c (hash_buf): New static function. (equal_hash): Route BUF type to hash_buf. * lib.c (buf_s): New symbol variable. (code2type): Handle BUF. (equal): Handle BUF using memcmp on the data. (obj_init): Intern buf symbol and initialize buf_s. * lib.h (type_t): New enum member BUF. (struct buf): New type. (union obj): New member b, of struct buf type. (buf_s): Declared.
* call-finalizers: allow recursion.Kaz Kylheku2017-03-231-40/+41
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | Code to invoke finalizers and remove them from the list is consolidated: both the gc and call-finalizers now use the same lower-level function. Finalizers may now themselves call-finalizers; it is no longer "unspecified behavior". This greatly improves the the TXR Lisp support for RAII, since :fini handlers of objects can call finalization on related objects. For instance a container being finalized can call the finalizers of contained objects. * gc.c (call_finalizers_impl): New function. Gathers all eligible finalizer registrations into a local list, first, removing them from the global list. Then does the calls in a second pass. Also, relative to the original functions which it replaces, this fixes an incorrect case: when the list is of length 1 and contains an eligible entry, in which case the global final_tail pointer is left aiming at a local variable! (is_reachable_final): New static function. (call_finalizers): Use call_finalizers_impl, specifying is_reachable_final as the predicate. (is_matching_final): New static function. (gc_call_finalizers): Use call_finalizers_impl, specifying is_matching_final as the predicate. * txr.1: Update documentation about call-finalizers.
* Rename badly named default_bool_argKaz Kylheku2017-03-171-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * lib.h (default_bool_arg): Inline function renamed to default_null_arg. * eval.c (if_fun, pad, ginterate, giterate, range_star, range, constantp, macroexpand_1, macro_form_p, expand_with_free_refs, do_expand, eval_intrinsic, func_get_name, make_env_intrinsic): Follow rename. * arith.c (lognot): Likewise. * gc.c (gc_finalize): Likewise. * glob.c (glob_wrap): Likewise. * hash.c (group_reduce, gethash_n): Likewise. * lib.c (print, multi_sort, lazy_str, vector, iff, tok_str, split_str_keep, search_str, remove_if, val): Likewise. * match.c (match_fun): Likewise. * parser.c (lisp_parse_impl, regex_parse): Likewise. * rand.c (make_random_state): Likewise. * regex.c (read_until_match, search_regex, regex_compile): Likewise. * socket.c (sock_accept, sock_connect): Likewise. * stream.c (open_files_star, open_files, run, open_process, open_tail, get_string, record_adapter): Likewise. * struct.c (static_slot_ensure, static_slot_ens_rec, clear_struct, make_struct_type): Likewise. * sysif.c (exec_wrap, errno_wrap, cobj_ops_init): Likewise. * unwind.c (uw_capture_cont, uw_find_frames_impl): Likewise.
* Bump copyright year to 2017.Kaz Kylheku2017-01-231-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | * LICENSE, LICENSE-CYG, METALICENSE, Makefile, args.c, args.h, arith.c, arith.h, cadr.c, cadr.h, combi.c, combi.h, configure, debug.c, debug.h, eval.c, eval.h, filter.c, filter.h, ftw.c, ftw.h, gc.c, gc.h, glob.c, glob.h, hash.c, hash.h, jmp.S, lib.c, lib.h, lisplib.c, lisplib.h, match.c, match.h, parser.c, parser.h, parser.l, parser.y, rand.c, rand.h, regex.c, regex.h, signal.c, signal.h, stream.c, stream.h, struct.c, struct.h, sysif.c, sysif.h, syslog.c, syslog.h, termios.c, termios.h, txr.1, txr.c, txr.h, unwind.c, unwind.h, utf8.c, utf8.h, share/txr/stdlib/awk.tl, share/txr/stdlib/build.tl, share/txr/stdlib/cadr.tl, share/txr/stdlib/conv.tl, share/txr/stdlib/except.tl, share/txr/stdlib/getopts.tl, share/txr/stdlib/getput.tl, share/txr/stdlib/hash.tl, share/txr/stdlib/ifa.tl, share/txr/stdlib/package.tl, share/txr/stdlib/path-test.tl, share/txr/stdlib/place.tl, share/txr/stdlib/socket.tl, share/txr/stdlib/struct.tl, share/txr/stdlib/tagbody.tl, share/txr/stdlib/termios.tl, share/txr/stdlib/txr-case.tl, share/txr/stdlib/type.tl, share/txr/stdlib/with-resources.tl, share/txr/stdlib/with-stream.tl, share/txr/stdlib/yield.tl: Add 2017 to all copyright headers and strings.
* Cancel in-progress gc if handling async signal.Kaz Kylheku2016-12-121-1/+24
| | | | | | | | | | | | | | | | | | | | If a signal goes off in the middle of gc that is routed to an async lambda handler, we should cancel gc, so the handler finds the heap in a good state. Of course, the handler must not return in this case, or else the interrupted gc will try to resume. * gc.c (inprogress): New static flag. (gc): Increment and decrement inprogress variable. Abort if re-entered. (gc_inprogress): New function. (unmark): Do not clear FREE flags, only REACHABLE. (gc_cancel): New function. * gc.h (gc_inprogress, gc_cancel): Declared. * signal.c (sig_handler): In the async lambda case, check for an in-progress gc and cancel it.
* Adjust some gen-gc array sizes.Kaz Kylheku2016-11-151-2/+2
| | | | | | | | | | | | | | Tuning some parameters by experimenting with timings. * gc.c (CHECKOBJ_VEC_SIZE): Reduce to 2*HEAP_SIZE; this doesn't have to be equal in size to FRESHOBJ_VEC_SIZE; entries into the checkobj array are not expected to be as frequent as in the freshobj array. (MUTOBJ_VEC_SIZE): On the other hand, at HEAP_SIZE/4, this may be too small. Increasing to 2*HEAP_SIZE. Overall, the storage for these arrays is reduced by over 25%, with seemingly better performance.
* Implementing package foreign symbol concept.Kaz Kylheku2016-11-101-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * eval.c (eval_init): Register new intrinsics: package-local-symbols, package-foreign-symbols, use-sym, unuse-sym, use-package, unuse-package, unintern. * gc.c (mark_obj): Mark new hidhash member of struct package. * lib.c (make_package): Initialize new hidhash member of struct package. (lookup_package): New static function. (find_package): Allow string or symbol argument. (get_package): New static function. (delete_package, package_symbols): Use get_package for flexible package argument; delete_package removes symbols from other packages via unuse_package. (package_local_symbols, package_foreign_symbols): New functions. (use_sym, unuse_sym): New functions. (resolve_package_designators): New static function. (use_package, unuse_package): New functions. (symbol_present): New static function. (intern): Revised with get_package for flexible package argument. (unintern): New function. (rehome_sym): Use get_package. Semantics revised. (obj_print_impl): Use symbol_present function to determine whether object is visible in *package* and can be printed without a prefix, rather than naive home package test. * lib.h (struct package): New member, hidhash. (package_local_symbols, package_foreign_symbols, use_sym, unuse_sym, use_package, unuse_package, unintern): Declared. * txr.1: Documentation updated. Extended section introducing the design of packages, and argument conventions. New functions described. Existing function descriptions revised, particularly rehome-sym. Missing description of delete-package added.
* Synchronize license comments with LICENSE.Kaz Kylheku2016-10-011-16/+17
| | | | | | | | | | | | | | | | | | | | * Makefile, args.c, args.h, arith.c, arith.h, cadr.c, cadr.h, combi.c, combi.h, configure, debug.c, debug.h, eval.c, eval.h, filter.c, filter.h, ftw.c, ftw.h, gc.c, gc.h, glob.c, glob.h, hash.c, hash.h, jmp.S, lib.c, lib.h, lisplib.c, lisplib.h, match.c, match.h, parser.c, parser.h, parser.l, parser.y, rand.c, rand.h, regex.c, regex.h, share/txr/stdlib/awk.tl, share/txr/stdlib/build.tl, share/txr/stdlib/cadr.tl, share/txr/stdlib/conv.tl, share/txr/stdlib/except.tl, share/txr/stdlib/hash.tl, share/txr/stdlib/ifa.tl, share/txr/stdlib/path-test.tl, share/txr/stdlib/place.tl, share/txr/stdlib/socket.tl, share/txr/stdlib/struct.tl, share/txr/stdlib/termios.tl, share/txr/stdlib/txr-case.tl, share/txr/stdlib/type.tl, share/txr/stdlib/with-resources.tl, share/txr/stdlib/with-stream.tl, share/txr/stdlib/yield.tl, signal.c, signal.h, socket.c, socket.h, stream.c, stream.h, struct.c, struct.h, sysif.c, sysif.h, syslog.c, syslog.h, termios.c, termios.h, txr.1, txr.c, txr.h, unwind.c, unwind.h, utf8.c, utf8.h: Revert to verbatim 2-Clause BSD.
* Rename EXTRA_DEBUGGING to CONFIG_EXTRA_DEBUGGING.Kaz Kylheku2016-06-171-5/+5
| | | | | | | | * configure: Generate #define CONFIG_EXTRA_DEBUGGING 1 in config.h header, rather than EXTRA_DEBUGGING. * gc.c, gc.h, hash.c: Change references to EXTRA_DEBUGGING preprocessor symbol to CONFIG_EXTRA_DEBUGGING.
* Print valgrind backtraces for break_obj.Kaz Kylheku2016-06-171-2/+28
| | | | | | | | | | | | * gc.c (more): Under EXTRA_DEBUGGING, call breakpt() here also, when it is detected that break_obj is added to the free list for the firts time. Print a message and backtrace using VALGRIND_PRINTF_BACKTRACE. (make_obj): Likewise, for an object that is pulled out of the free list and returned. (mark_obj, sweep_one): Print backtrace with Valgrind for break_obj, in addition to calling breakpt().
* Useful assertion in make_obj.Kaz Kylheku2016-06-171-0/+1
| | | | | * gc.c (make_obj): Assert that the object we are pulling from the free list is marked FREE.
* gc bugfix: maintain free_tail properly.Kaz Kylheku2016-06-161-5/+6
| | | | | | | | | | | | | * gc.c (more): Only set the free_tail if the new memory is being added to an empty free_list. Otherwise free_tail is valid. (make_obj): If we empty the free_list, then reset the free_tail pointer, so it doesn't continue pointing into the object we are returning. (sweep): Remove defensive code which tries to reset the free_tail in the empty free_list case, but assumes that free_tail is correct in the non-empty case.
* Remove more vestiges of the mark_makefresh hack.Kaz Kylheku2016-06-161-16/+3
| | | | | | | | | | * gc.c (sweep_one): Don't check for gen == -1; no reachable object can have that at this stage, since mark flips -1 objects to gen 0. (sweep): Do not clear freshobj_idx here; completely revert the mark_markfresh code. (gc): Clear freshobj_idx here., as before the mark_makefresh hack.
* New --free-all option for freeing memory on exit.Kaz Kylheku2016-06-071-0/+40
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Although we are garbage-collected, being able to clean up on shutdown is nevertheless useful for uncovering leaks. Leaks can occur, for instance, due to neglect to free out-of-heap satellite data from objects that are reclaimed by gc. This feature is long overdue. * arith.c, arith.h (arith_free_all): New function. * gc.c, gc.h (gc_free_all): New function. * lib.c (init): Remove program name parameter and redundant initialization of progname globl variable. * lib.h (progname): Superfluous declaration removed. This is already declared in txr.h. (init): Declaration updated. * regex.c (char_set_destroy): Do not check the static allocation flag here; just destroy the object. Do check for a null pointer, though. (char_set_cobj_destroy): This cobj destructor now checks the static flag of the char set object and avoids freeing it. Thus our char set singletons are left alone by gc, but our global freeing function takes care of them. (wide_cs): New static variable moved out of wide_display_char_p to static scope. (regex_free_all): New function. * regex.h (regex_free_all): Declared. * txr.c (progname): const qualifier and initializer removed. (main): Ensure progname is always dynamically allocated, even in the argv[0] == 0 case. Do not pass progname to init; it doesn't take that argument any more. (free_all): New static function. (txr_main): Implement --free-all option. * txr.h (progname): Declaration updated.
* Fix incorrect comment.Kaz Kylheku2016-05-151-1/+1
| | | | | * gc.c (gc_set): Should say "promote obj to gen 1", not "to gen 0".
* Mechanism for recycling conses outside of GC.Kaz Kylheku2016-04-201-0/+1
| | | | | | | | | | | | * lib.c (recycled_conses): New static variable. (rcyc_pop, rcyc_cons, rcyc_list, rcyc_empty): New functions. (cons): Take a recycled cons, if available. * lib.h (rcyc_pop, rcyc_cons, rcyc_list, rcyc_empty): Declared. * gc.c (gc): Call rcyc_empty to make recycle_list unreachable.
* Replace all stray C style casts with macros.Kaz Kylheku2016-03-291-1/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * gc.c (gc_report_copies): C style casts found in this function. * linenoise.c (strip_qual, convert, coerce): Copy and paste the macros here. (record_undo, compare_completions, lino_add_completion, history_search, ab_append, sync_data_to_buf, refresh_singleline, screen_rows, refresh_multiline, find_nearest_paren, paren_jump, yank_sel, edit_move_matching_paren, edit, lino_make, lino_copy, lino_hist_add, lino_hist_set_max_len): C style casts replaced. * mpi/mpi-types.h (MP_DIGIT_BIT, MP_DIGIT_MAX, MP_WORD_BIT, MP_WORD_MAX, RADIX): C style casts replaced. * mpi/mpi.c (convert, coerce): Copy and paste the macros here. (mp_init_size, mp_init_copy, mp_copy, mp_set_int, mp_div_d, mp_bit, mp_to_double, mp_to_signed_bin, mp_to_unsigned_bin, mp_to_unsigned_buf, mp_toradix_case, mp_grow, s_mp_set_bit, s_mp_mod_2d, s_mp_mul_2d, s_mp_div_2d, s_mp_mul_d, s_mp_mul, s_mp_sqr, s_mp_div, s_mp_2expt, s_mp_todigit): C style casts replaced. * mpi/mplogic (convert): Macro copy and pasted here. (mpl_num_set, mpl_num_clear): C style casts replaced. * parser.c (provide_completions): Likewise. * signal.c (small_sigfillset): Likewise. * stream.c (stdio_truncate, test_set_indent_mode, set_indent_mode): Likewise.
* Use struct instead of cons for lazy string fields.Kaz Kylheku2016-01-091-2/+6
| | | | | | | | | | | | | | | | * gc.c (finalize): Must free the dynamic structure attached to the LSTR type now. (mark_obj): Must mark interior of LSTR type's props structure. * lib.c (lazy_sub_str, copy_lazy_str): Copy props structure. (lazy_str): Allocate and initialize props structure. (lazy_str_force, lazy_str_put, lazy_str_force_upto, lazy_str_get_trailing_list, out_lazy_str): Follow representation change. * lib.h (struct lazy_string_props): New struct type. (strut lazy_string): Member opts replaced with props pointer to struct lazy_string_props.
* Copyright year bump.Kaz Kylheku2015-12-311-1/+1
| | | | | | | | | | | | | | | | | | | | | | | * LICENSE, METALICENSE, Makefile, args.c, args.h, arith.c, arith.h, cadr.c, cadr.h, combi.c, combi.h, configure, debug.c, debug.h, eval.c, eval.h, filter.c, filter.h, gc.c, gc.h, glob.c, glob.h, hash.c, hash.h, jmp.S, lib.c, lib.h, lisplib.c, lisplib.h, match.c, match.h, parser.c, parser.h, parser.l, parser.y, rand.c, rand.h, regex.c, regex.h, share/txr/stdlib/cadr.tl, share/txr/stdlib/except.tl, share/txr/stdlib/hash.tl, share/txr/stdlib/ifa.tl, share/txr/stdlib/path-test.tl, share/txr/stdlib/place.tl, share/txr/stdlib/struct.tl, share/txr/stdlib/txr-case.tl, share/txr/stdlib/type.tl, share/txr/stdlib/with-resources.tl, share/txr/stdlib/with-stream.tl, share/txr/stdlib/yield.tl, signal.c, signal.h, stream.c, stream.h, struct.c, struct.h, sysif.c, sysif.h, syslog.c, syslog.h, txr.1, txr.c, txr.h, unwind.c, unwind.h, utf8.c, utf8.h: Add 2016 copyright. * linenoise/LICENSE, linenoise/linenoise.c, linenoise/linenoise.h: Bump one principal author's copyright from 2014 to 2015. The code is based on a snapshot of 2015 upstream work.
* Useful debugging function for spurious retention.Kaz Kylheku2015-11-201-0/+12
| | | | | | * gc.c (gc_report_copies): New function * gc.h (gc_report_copies): Declared.
* Remove unused rel1 function.Kaz Kylheku2015-11-061-7/+0
| | | | | | * gc.c (rel1): Removed. * gc.h (rel1): Declaration removed.
* New range type, distinct from cons cell.Kaz Kylheku2015-11-011-0/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * eval.c (eval_init): Register intrinsic functions rcons, rangep from and to. (eval_init): Register rangep intrinsic. * gc.c (mark_obj): Traverse RNG objects. (finalize): Handle RNG in switch. * hash.c (equal_hash, eql_hash): Hashing for for RNG objects. * lib.c (range_s, rcons_s): New symbol variables. (code2type): Handle RNG type. (eql, equal): Equality for ranges. (less_tab_init): Table extended to cover RNG. (less): Semantics defined for ranges. (rcons, rangep, from, to): New functions. (obj_init): range_s and rcons_s variables initialized. (obj_print_impl): Produce #R notation for ranges. (generic_funcall, dwim_set): Recognize range objects for indexing * lib.h (enum type): New enum member, RNG. MAXTYPE redefined to RNG value. (TYPE_SHIFT): Increased to 5 since there are now 16 type codes. (struct range): New struct type. (union obj): New member rn, of type struct range. (range_s, rcons_s, rcons, rangep, from, to): Declared. (range_bind): New macro. * parser.l (grammar): New rule for recognizing the #R sequence as HASH_R token. * parser.y (HASH_R): New terminal symbol. (range): New nonterminal symbol. (n_expr): Derives the new range symbol. The n_expr DOTDOT n_expr rule produces rcons expression rather than const. * match.c (format_field): Recognize rcons syntax in fields which is now what ranges translate to. Also recognize range object. * tests/013/maze.tl (neigh): Fix code which destructures range as a cons. That can't be done any more. * txr.1: Document ranges.