| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
|
| |
* gc.[ch] (gc_prot_array_alloc): Return the COBJ via
new pointer argument.
* lib.c (ssort_vec): Capture the object from gt_prot_array_alloc
into a local variable, That makes it visible to the garbage
collector, so it won't be prematurely reclaimed. Since we don't
use or return that object, we need to use gc_hint.
|
|
|
|
|
|
|
|
|
|
| |
This C++ regression snuck into in Version 286; I didn't
check C++ compilation.
* lib.h (container): Macro must use coerce not
convert because mem_t * isn't void *.
* gc.c (gc_prot_array_alloc): Likewise.
|
|
|
|
|
|
|
|
|
|
| |
* gc.c (gc_free_all): Just like we do in the sweep function,
we must mask back the pointer tag that we removed from
the heap object's pointer, before handing the pointer to
the free function. Starting in Android 11, the pointer
tagging is more strict. It was not enforced previously; now
our logic for stripping and restoring the tags is actualy
being tested.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* gc.c (mark_obj_norec): New function. Just marks
an object reachable without recursing over its
sub-objects.
(gc_mark_norec): New function.
* gc.h (gc_mark_norec): Declared.
* hash.c (do_weak_tables): Cache the table, mask and
vector pointer in a local variable, since these pointers
are not expected to change across function calls, and
can go into registers.
When visiting an entry that should be reachable, we
mark that entry immediately, and also use the new
gc_mark_norec function to mark the chain cons cell
reachable. I.e. we mark the chain backbone cons,
and that cons' car field, that being the entry.
Thus by the time we march through the chain, we
have marked all of it. Thus, the table entries don't
have to be iterated and marked any more. We use
gc_mark_norec to mark the table, and explicitly mark
its two special slots. The upshot of all this is that
we don't have to make an extra pass over the table,
and the chains, to mark things; we combine the marking
with the expunging of weak values.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* gc.c (prot_array): Add self pointer; arr member
becomes flexible array.
(prot_array_mark): We now check the handle itself for
null, because the whole thing is freed.
(prot_array_free): Function removed.
(prot_array_ops): Wire cobj_destroy_free_op in place
of prot_array_free. This fixes a memory leak because
prot_array_free was not freeing the handle, only
the array.
(gc_prot_array_alloc): Fix to allocate everything
in one swoop and store the self-pointer in the
named member rather than arr[-1]. The self argument
is not required; we drop it. The size argument cannot
be anywhere near INT_PTR_MAX, because such an array
wouldn't fit into virtual memory, so it is always
safe to add a small value to the size.
(prot_array_free): Obtain the self-pointer, and
free the handle, replacing it with a null pointer.
* gc.h (gc_prot_array_alloc): Declaration updated.
* lib.c (ssort_vec): Don't pass self to gc_prot_array_alloc.
* lib.h (container): New macro.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
For array-like objecgts, these objects use an
array-based merge sort, using an auxiliary array
equal in size to the original array.
To provide the auxiliary array, a new kind of very simple
vector-like object is introduced into the gc module: protected
array. This looks like a raw dynamic C array of val type,
returned as a val *. Under the hood, there is a heap object
there, which makes the array traversable by the garbage
collector.
The whole point of this exercise is to make the new mergesort
function safe even if the caller-supplied functions misbehave
in such a way that the auxiliary array holds the only
references to heap objects.
* gc.c (struct prot_array): New struct,
(prot_array_cls): New static variable.
(gc_late_init): Register COBJ class, retaining in
prot_array_cls.
(prot_array_mark, prot_array_free): New static functions.
(prot_array_ops): New static structure.
(prot_array_alloc, prot_array_free): New functions.
* gc.h (prot_array_alloc, prot_array_free): Declared.
* lib.c (mergesort, ssort_vec): New static function.
(snsort, ssort): New functions.
* lib.h (snsort, ssort): Declared.
* tests/010/sort.tl: Cover ssort.
* txr.1: Documented.
* stdlib/doc-syms.tl: Updated.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This fixes only the build. I'm getting a crash in
one test case, namely tests/010/json.tl.
* lib.h (mut): Remove stray semicolon from definition.
This semicolon compensates for the lack of a semicolon
in txr.c, which becomes a syntax errror under no-gen-gc,
when the other definition of mut is active.
(mkloc, setcheck): Let's add casts of the object argument
to void. This gets rid of a number of unused parameter
errors in various functions that take an object parameter
that is only used in the case of generational GC.
* txr.c (txr_main): Add missing semicolon after mut call.
* gc.c (gc_wrap): In the no CONFIG_GEN_GC case, cast
argument full to void, since it is unused.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* LICENSE, LICENSE-CYG, METALICENSE, Makefile, alloca.h,
args.c, args.h, arith.c, arith.h, autoload.c, autoload.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, gzio.c,
gzio.h, hash.c, hash.h, itypes.c, itypes.h, jmp.S,
lex.yy.c.shipped, lib.c, lib.h, linenoise/linenoise.c,
linenoise/linenoise.h, match.c, match.h, parser.c, parser.h,
parser.l, parser.y, protsym.c, psquare.h, rand.c, rand.h,
regex.c, regex.h, signal.c, signal.h, socket.c, socket.h,
stdlib/arith-each.tl, stdlib/asm.tl, stdlib/awk.tl,
stdlib/build.tl, stdlib/cadr.tl, stdlib/compiler.tl,
stdlib/constfun.tl, stdlib/conv.tl, stdlib/copy-file.tl,
stdlib/debugger.tl, stdlib/defset.tl, stdlib/doloop.tl,
stdlib/each-prod.tl, stdlib/error.tl, stdlib/except.tl,
stdlib/ffi.tl, stdlib/getopts.tl, stdlib/getput.tl,
stdlib/hash.tl, stdlib/ifa.tl, stdlib/keyparams.tl,
stdlib/match.tl, stdlib/op.tl, stdlib/optimize.tl,
stdlib/package.tl, stdlib/param.tl, stdlib/path-test.tl,
stdlib/pic.tl, stdlib/place.tl, stdlib/pmac.tl,
stdlib/quips.tl, stdlib/save-exe.tl, stdlib/socket.tl,
stdlib/stream-wrap.tl, stdlib/struct.tl, stdlib/tagbody.tl,
stdlib/termios.tl, stdlib/trace.tl, stdlib/txr-case.tl,
stdlib/type.tl, stdlib/vm-param.tl, stdlib/with-resources.tl,
stdlib/with-stream.tl, stdlib/yield.tl, stream.c, stream.h,
struct.c, struct.h, strudel.c, strudel.h, sysif.c, sysif.h,
syslog.c, syslog.h, termios.c, termios.h, time.c, time.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,
y.tab.c.shipped: Copyright year bumped to 2023.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
On platforms which have the malloc_usable_size function,
we don't have to store the allocated size of an object;
malloc provides us the allocated size (which may be larger
than we requested). Here we take advantage of this for
strings. And since we don't have to store the string
allocated size any more, we use that field for something
else: storing the hash code (for seed zero). This can speed
up some hashing operations.
* configure (have_malloc_usable_size): New variable.
Configure test for have_malloc_usable size. We have to
try several header files, too. We set the configure
variable HAVE_MALLOC_USABLE_SIZE, and possibly
HAVE_MALLOC_H or HAVE_MALLOC_NP_H.
* lib.h (struct string): If HAVE_MALLOC_USABLE_SIZE
is true, we define a member called hash insetad of
alloc. Also, we change alloc to cnum.
* lib.c: Include <malloc_np.h> if HAVE_MALLOC_NP_H
is defined.
(string_own, string, string_utf8, mkstring, mkustring,
init_str, string_extend, string_finish, string_set_code,
string_get_code, length_str, replace_str, chr_str_set):
Fix code for both cases. On platforms with malloc_usable_size,
we have the allocated size from malloc, so we don't have to
retrieve it from the object or store it. Any operations which
mutate the string must reset the hash field to zero; zero
means "hash has not been calculated".
* hash.c (equal_hash): Just retrive a string's hash value, if
it is nonzero, otherwise calculate, cache it and return it.
* gc.c (mark_obj): The alloc member of struct string is a
machine integer now; no need to mark it.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We strip Android's pointer tag from our heap
pointer while we own it, then put it back at
free time.
* configure (android_target): New variable.
Set this to y in the test where we detect Android.
When setting CONFIG_NAN_BOXING, also set
CONFIG_NAN_BOXING_STRIP_TAG if on Android.
* gc.c (struct heap): New member, tag.
(more): When tag stripping is enabled, clear the
top 16 bits of the pointer coming from malloc,
and keep those bits in heap->tag. This gets rid
of Android's tag.
(sweep): When releasing a heap block with free,
we must put the tag back into the pointer, from
heap->tag.
|
|
|
|
|
| |
* gc.c (mark_obj_maybe): Avoid declaration after statement,
which is enforced when configured in --maintainer mode.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* gc.c (sweep_one): The recent fix to address the clang
diagnostic from -fsanitize=implicit-conversion broke C++
compatibility, due to enums being type safe. We revert the
expression to the original, before that fix, and address the
clang diagnostic differently.
* gc.h (REACHABLE, FREE): Add a U suffix to the constants to
make them unsigned. The implicit conversion issue in the
expression convert(type_t, block->t.type & ~REACHABLE)
is that ~REACHABLE is -257, and is being converted to
unsigned.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The implicit conversions were discovered with Clang's UBSan (with
the -fsanitizer=implicit-conversion option).
* gc.c (sweep_one): Convert only the inverted REACHABLE, since
block->t.type is already of the right type.
* hash.c (eql_hash, eq_hash, hash_iter_init, us_hash_iter_init):
Explicitly convert to ucnum.
* linenoise/linenoise.c (enable_raw_mode): Explicitly convert the
inverted flag sets to tcflag_t.
* mpi/mpi.c (mp_set_uintptr): Explicitly convert to uint_ptr_t.
* regex.c (char_set_add): Explicitly convert to bitcell_t.
* struct.c (struct_inst_hash): Correct type of hash from cnum to
ucnum.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
*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,
lex.yy.c.shipped, 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, psquare.h,
rand.c, rand.h, regex.c, regex.h, signal.c, signal.h,
socket.c, socket.h, stdlib/arith-each.tl, stdlib/asm.tl,
stdlib/awk.tl, stdlib/build.tl, stdlib/cadr.tl,
stdlib/compiler.tl, stdlib/constfun.tl, stdlib/conv.tl,
stdlib/copy-file.tl, stdlib/debugger.tl, stdlib/defset.tl,
stdlib/doloop.tl, stdlib/each-prod.tl, stdlib/error.tl,
stdlib/except.tl, stdlib/ffi.tl, stdlib/getopts.tl,
stdlib/getput.tl, stdlib/hash.tl, stdlib/ifa.tl,
stdlib/keyparams.tl, stdlib/match.tl, stdlib/op.tl,
stdlib/optimize.tl, stdlib/package.tl, stdlib/param.tl,
stdlib/path-test.tl, stdlib/pic.tl, stdlib/place.tl,
stdlib/pmac.tl, stdlib/quips.tl, stdlib/save-exe.tl,
stdlib/socket.tl, stdlib/stream-wrap.tl, stdlib/struct.tl,
stdlib/tagbody.tl, stdlib/termios.tl, stdlib/trace.tl,
stdlib/txr-case.tl, stdlib/type.tl, stdlib/vm-param.tl,
stdlib/with-resources.tl, stdlib/with-stream.tl,
stdlib/yield.tl, stream.c, stream.h, struct.c, struct.h,
strudel.c, strudel.h, sysif.c, sysif.h, syslog.c, syslog.h,
termios.c, termios.h, time.c, time.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, y.tab.c.shipped: Copyright year
bumped to 2022.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The use of -ansi doesn't by itself diagnose instances of some
constructs we don't want in the project, like mixed
declarations and statements.
* configure (diag_flags): Add -Werror=declaration-after-statement.
This is C only, so filter it out for C++.
Also add -Werror=vla.
* HACKING: Update inaccurate statements about what dialect we
are using. TXR isn't pure C90: some GCC extensions are used.
We even use long long if the configure script detects it as
working, and some C99 library features.
* buf.c (replace_buf, buf_list): Fix by reordering.
* eval.c (op_dohash, op_load_time_lit): Fix by reordering.
* ffi.c (ffi_simple_release): Fix by reordering.
(align_sw_get): Fix empty macro to expand to dummy declaration
so a semicolon after it isn't interpreted as a statement.
On platforms with alignment, remove a semicolon from the macro
so that it requires one.
(ffi_i8_put, ffi_u8_put): Fix by reordering.
* gc.c (gc_init): Fix with extra braces.
* hash.c (hash_init): Fix by reordering.
* lib.c (list_collect_revappend, sub_iter, replace_str,
replace_vec, mapcar_listout, mappend, mapdo, window_map_list,
subst): Fix by reordering.
(gensym, find, rfind, pos, rpos, in, search_common): Fix by
renaming optional argument and using declaration instead of
assignment.
* linenoise/linenoise.c (edit_in_editor): Fix by reordering.
* parser.c (is_balanced_line): Fix by reordering.
* regex.c (nfa_count_one, print_rec): Fix by reordering.
* signal.c (sig_mask): Fix by reordering.
* stream.c (get_string): Fix by renaming optional argument and
using declaration instead of assignment.
* struct.c (lookup_static_slot_desc): Fix by turning mutated
variable into block local.
(umethod_args_fun): Fix by reordering.
(get_special_slot): Fix by new scope via braces.
* sysif.c (usleep_wrap): Fix by new scope via braces.
(setrlimit_wrap): Fix by new scope via braces.
* time.c (time_string_meth, time_parse_meth): Fix by reordering.
* tree.c (tr_do_delete_spec): Fix by new scope via braces.
* unwind.h (uw_block_beg): New macro which doesn't define
RESULTVAR but expects it to refers to an existing one.
(uw_block_begin): Replace do while (0) with enum trick
so that we have a declaration that requires a semicolon,
rather than a statement, allowing declarations to follow.
(uw_match_env_begin): Now opens a scope and features the
same enum trick as in uw_block_begin.
This fixes a declaration-follows-statement issue in
the v_output function in match.c.
(uw_match_env_end): Closes scope opened by uw_match_env_begin.
* unwind.c (revive_cont): Fix by introducing variable, and
using new uw_block_beg macro.
* vm.c (vm_execute_closure): Fix using combination of local
variable and reordering.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* Makefile, alloca.h, args.c, args.h, arith.c, arith.h, buf.c,
buf.h, chksum.c, chksum.h, chksums/crc32.c, chksums/crc32.h,
combi.c, combi.h, 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, rand.c, rand.h, regex.c,
regex.h, signal.c, signal.h, socket.c, socket.h,
stdlib/asm.tl, stdlib/awk.tl, stdlib/build.tl,
stdlib/compiler.tl, stdlib/constfun.tl, stdlib/conv.tl,
stdlib/copy-file.tl, stdlib/debugger.tl, stdlib/defset.tl,
stdlib/doloop.tl, stdlib/each-prod.tl, stdlib/error.tl,
stdlib/except.tl, stdlib/ffi.tl, stdlib/getopts.tl,
stdlib/getput.tl, stdlib/hash.tl, stdlib/ifa.tl,
stdlib/keyparams.tl, stdlib/match.tl, stdlib/op.tl,
stdlib/optimize.tl, stdlib/package.tl, stdlib/param.tl,
stdlib/path-test.tl, stdlib/pic.tl, stdlib/place.tl,
stdlib/pmac.tl, stdlib/quips.tl, stdlib/save-exe.tl,
stdlib/socket.tl, stdlib/stream-wrap.tl, stdlib/struct.tl,
stdlib/tagbody.tl, stdlib/termios.tl, stdlib/trace.tl,
stdlib/txr-case.tl, stdlib/type.tl, stdlib/vm-param.tl,
stdlib/with-resources.tl, stdlib/with-stream.tl,
stdlib/yield.tl, stream.c, stream.h, struct.c, struct.h,
strudel.c, strudel.h, sysif.c, sysif.h, syslog.c, syslog.h,
termios.c, termios.h, time.c, time.h, tree.c, tree.h, txr.c,
txr.h, unwind.c, unwind.h, utf8.c, utf8.h, vm.c, vm.h, vmop.h:
License reformatted.
* lex.yy.c.shipped, y.tab.c.shipped, y.tab.h.shipped: Updated.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The functions copy-cons, copy-tree, copy-fun and copy-tnode have a
problem. They copy the original object bitwise with a structure
assignment, and then make some adjustments. The problem is that this
inappropriately copies the object's metadata related to gc, such as its
generation number or finalization count. To fix this, we introduce a
copy_obj function, which is a companion to make_obj. This performs a
shallow copy of an object without incorrectly propagating inappropriate
metadata.
* gc.c, gc.h (copy_obj): New function.
* lib.c (copy_fun, copy_cons, copy_tree): Use copy_obj, instead of
make_obj plus structure assignment.
* tree.c (copy_tnode): Likewise.
|
|
|
|
|
|
| |
* gc.c (mark_obj): We don't need to mark this because it's
necessarily a protected symbol handled by prot_sym.
Waste of cycles.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This is a big commit motivated by the need to clean up the
situation with built-in type symbols, COBJ objects and
structs.
The struct type system allows struct types to be defined
for symbols like regex or str, which are used by built-in
or cobj types. This is a bad thing.
What is worse, structure instances are COBJ types which
identify their type using the COBJ class symbol mechanism.
There are places in the C implementation which assume
that when a COBJ has a certain class symbol, it is of
a certain expected type, which is totally different from
and incompatible form a struct instance. User code can
define a structure object which will fool that code.
There are multiple things going on in this patch.
The major theme is that the COBJ representation is changing.
Instead of a class symbol, COBJ instances now carry a
"struct cobj_class *" pointer. This pointer is obtained
by registration via the cobj_register function. All modules
must register their class symbols to obtain these class
handles, which are then used in cobj() calls for
instantiation.
The CPTR type was identical to COBJ until now, except for the
type tag. This is changing; CPTR objects will keep the old
representation with the class symbol.
commit 20fdfc6008297001491308849c17498c006fe7b4
Author: Kaz Kylheku <kaz@kylheku.com>
Date: Thu Jul 8 19:17:39 2021 -0700
* ffi.h (carray_cls): Declared.
* hash.h (hash_cls): Declared.
(hash_early_init): Declared.
* lib.h (struct cobj_class): New struct.
(struct cobj): cls member changing to struct cobj_class *.
(struct cptr): New struct, same as previous struct cobj.
(union obj): New member cp of type struct cptr, for CPTR.
(builtin_type): Declared.
(class_check): Declaration moved closer to COBJ-related
functions and updated.
(cobj_register, cobj_register_super, cobj_class_exists): New
functions declared.
(cobjclassp, cobj_handle, cobj_ops): Declarations updated.
* parser.h (parser_cls): Declared.
* rand.h (random_state_cls): Declared.
* regex.h (regex_cls): Declared.
* stream.h (stream_cls, stdio_stream_cls): Declared.
* struct.h (struct_cls): Declared.
* tree.h (tree_cls, tree_iter_cls): Declared.
* vm.h (vm_desc_cls): Declared.
* buf.c (buf_strm, make_buf_stream): Pass stream_cls
functions instead of stream_s class symbol.
* chksum.c (sha256_ctx_cls, md5_ctx_cls): New static class
handles.
(sha256_begin, sha256_hash, sha256_end, md5_begin, md5_hash,
md5_end): Pass class handles to instead of class symbols.
(chksum_init): Initialize class handle variables.
* ffi.c (ffi_type_cls, ffi_call_desc_cls, ffi_closure_cls,
union_cls): New static class handles.
(carray_cls): New global variable.
(ffi_type_struct_checked, ffi_type_print_op,
ffi_closure_struct_checked, ffi_closure_print_op,
make_ffi_type_builtin, make_ffi_type_pointer,
make_ffi_type_struct, make_ffi_type_union,
make_ffi_type_array, make_ffi_type_enum,
ffi_call_desc_checked, ffi_call_desc_print_op,
ffi_make_call_desc, ffi_make_closure, carray_struct_checked,
carray_print_op, make_carray, cptr_getobj, cptr_out,
uni_struct_checked, make_union_common): Pass class handles
instead of class symbols.
(ffi_init): Initialize class handle variables.
* filter.c (regex_from_trie): Use hash_cls class handle
instead of hash_s.
* gc.c (mark_obj): Split COBJ and CPTR cases since the
representation is different.
* hash.c (hash_cls, hash_iter_cls): New class handles.
(make_similar_hash, copy_hash, gethash_c, gethash_e, remhash,
clearhash, hash_count, get_hash_userdata, set_hash_userdata,
hashp, hash_iter_init, hash_begin, hash_next, hash_peek,
hash_reset, hash_reset, hash_uni, hash_diff, hash_symdiff,
hash_isec): Pass class handles instead of class symbols.
(hash_early_init): New function.
(hash_init): Set the class symbols in the class handles that
were created in hash_early_init at a time when these symbols
did not exist.
* lib.c (nelem): New macro.
(cobj_class): New static array.
(cobj_ptr): New static pointer.
(cobj_hash): New static hash.
(seq_iter_cls): New static class handle.
(builtin_type_p): New function.
(typeof): Struct instances now all carry the same symbol,
struct, as their COBJ class symbol. To get their type, we must
call struct_type_name.
(subtypep): Rearrangement of two cases: let's make the
reflexive case first. Adjust code for different location
of COBJ class symbol.
(seq_iter_init_with_info, seq_begin, seq_next, seq_reset,
iter_begin, iter_more, iter_item, iter_step, iter_reset,
make_like, list_collect, do_generic_funcall): Use class
handles instead of class symbols.
(class_check, cobj, cobjclassp, cobj_handle, cobj_ops): Take
class handle argument instead of class symbol.
(cobj_register, cobj_register_super, cobj_class_exists): New
functions.
(cobj_populate_hash): New static function.
(cobj_print_op): Adjust for different location of class
(cptr_print_op, cptr_typed, cptr_type, cptr_handle,
cptr_get): cptr functions now refer to obj->cp rather than
obj->co.
(copy, length, sub, ref, refset, replace, dwim_set, dwim_del,
obj_print): Use class handles for various COBJ types rather
than class symbols.
(obj_init): gc-protect cobj_hash. Initialize seq_iter_cls
class symbol and cobj_hash. Populate cobj_hash as the last
initialization step.
(init): Call hash_early_init immediately after gc_init.
diff --git a/lib.c b/lib.c
* match.c (do_match_line): Refer to regex_cls class handle
instead of regex_s..
* parser.c (parser_cls): New global class handle.
(parse, parser_get_impl, lisp_parse_impl, txr_parse,
parser_errors): Use class handles instead of class symbols.
(parse_init): Initialize parser_cls.
* rand.c (random_state_cls): New global class handle.
(make_state, random_state_p, make_random_state,
random_state_get_vec, random_fixnum, random_float, random):
Use class handles instead of class symbols.
(rand_init): Initialize random_state_cls.
* regex.c (regex_cls): New global class handle.
(chset_cls): New static class handle.
(reg_compile_csets, reg_derivative, regex_compile, regexp,
regex_source, regex_print, regex_run, regex_machine_init): Use
class handles instead of class symbols.
(regex_init): Initialize regex_cls and chset_cls.
* socket.c (make_dgram_sock_stream): Use stream_cls class
symbol instead of stream_s.
* stream.c (stream_cls, stdio_stream_cls): New class handles.
(make_null_stream, stdio_get_fd, make_stdio_stream_common,
stream_fd, sock_family, sock_type, sock_peer, sock_set_peer,
make_dir_stream, make_string_input_stream,
make_string_byte_input_stream, make_strlist_input_stream,
make_string_output_stream, make_strlist_output_stream,
get_list_from_stream, make_catenated_stream,
make_delegate_stream, make_delegate_stream, stream_set_prop,
stream_get_prop, close_stream, get_error, get_error_str,
clear_error, get_line, get_char, get_byte, get_bytes,
unget_char, unget_byte, put_buf, fill_buf, fill_buf_adjust,
get_line_as_buf, format, put_string, put_char, put_byte,
flush_stream, seek_stream, truncate_stream, get_indent_mode,
test_set_indent_mode, test_neq_set_indent_mode,
set_indent_mode, get_indent, set_indent, inc_indent,
width_check, force_break, set_max_length, set_max_depth): Use
class handle instead of symbol.
(stream_init): Initialize stream_cls and stdio_stream_cls.
* struct.c (struct_type_cls, struct_cls): New class handles.
(struct_init): Initialize struct_type_cls and struct_cls.
(struct_handle): Static function moved to avoid forward
declaration.
(stype_handle): Refer to struct_type_cls class handle instead
of struct_type_s symbol. Handle instance objects in addition
to types.
(make_struct_type): Throw error if a built-in type is being
defined as a struct type. Refer to class handle instead of
class symbol.
(find_struct_type, allocate_struct, make_struct_impl,
make_lazy_struct, copy_struct): Refer to class handle instead of
class symbol.
* strudel.c (make_struct_delegate_stream): Refer to stream_cls
class handle instead of stream_s symbol.
* sysif.c (dir_cls): New class handle.
(poll_wrap): Use typep instead of subtypep, eliminating access
to class symbol.
(opendir_wrap, closedir_wrap, readdir_wrap): Use class handles
instead of class symbols.
(sysif_init): Initialize dir_cls.
* syslog.c (make_syslog_stream): Refer to stream_cls class
handle instead of stream_s symbol.
* tree.c (tree_cls, tree_iter_cls): New class handles.
(tree_insert_node, tree_lookup_node, tree_delete_node,
tree_root, tree_equal_op, tree, copy_search_tree,
make_similar_tree, treep, tree_begin, copy_tree_iter,
replace_tree_iter, tree_reset, tree_next, tree_peek,
tree_clear): Use class handle instead of class symbol.
(tree_init): Initialize tree_cls and tree_iter_cls.
* unwind.c (sys_cont_cls): New static class handle.
(revive_cont, capture_cont): Use class handle instead of class
symbol.
(uw_late_init): Initialize sys_cont_cls.
* vm.c (vm_desc_cls): New global class handle.
(vm_closure_cls): New static class handle.
(vm_desc_struct, vm_make_desc, vm_closure_struct,
vm_make_closure, vm_copy_closure): Use class handle instead of
class symbol.
(vm_init): Initialize vm_desc_cls and vm_closure_cls.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* gc.c (MIN_STACK_LIMIT): New preprocessor symbol.
(gc_init): If the system stack limit is too low, don't
treat that the same way as a missing or unlimited limit.
Instead clamp to the minimum value and hope for the best.
So that is to say, the system limit cannot be used as a
mechanism to set a ridiculously low stack limit in TXR; the
only way to do that is to use the set-stack-limit function.
* txr.1: Documentation updated. Also fixed 326767 typo which
should be 32767.
|
|
|
|
|
|
|
|
|
|
|
| |
Even if built without getrlimit, and even if getrlimit
reports an unlimited stack size, set up a default limit.
* gc.c (DFL_STACK_LIMIT): New preprocessor symbol, defined as
128 kilbytes for a small memory configuration, otherwise
16 megabytes.
(gc_init): Set up a default stack limit unconditionally
based on DFL_STACK_LIMIT before probing getrlimit.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* gc.c (gc_init): We must check rlim_cur for the RLIM_INFINITY
value indicating unlimited stack, and not misuse this value as a
limit number, otherwise hilarity ensues. This reproduced on
an older platform with make 3.81, which calls setrlimit to
bring about an unlimited stack, passed on to child processes.
Because of this txr segfaulted, as a consequence of a false
positive.
* tests/012/stack.tl (stack-limited): New variable which
indicates whether there is a stack limit. If there isn't, we
avoid running the fork-based test case. Also, we set the stack
limit to 32768 so we have a limit against which to run some of
the tests.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* configure: detect getrlimit, producing HAVE_RLIMIT in
config.h.
* eval.c (do_eval, do_expand): Call gc_stack_check inline
function to check stack pointer against limit.
* gc.c (gc_stack_bottom): Static becomes extern, so inline
function in gc.h can refer to it.
(gc_stack_limit): New global variable.
(gc_init): If we have rlimit, then probe RLIMIT_STACK.
If the stack is sufficiently large, then enable the stack
overflow protection, which kicks in when the stack pointer
appears to be within a certain percentage of the limit.
(set_stack_limit, get_stack_limit): New static functions.
(gc_late_init): Register set-stack-limit and get-stack-limit
intrinsics.
(gc_stack_overflow): New function.
* gc.h (gc_stack_bottom, gc_stack_limit, gc_stack_overflow):
Declared.
(gc_stack_check): New inline function.
* lib.c (stack_overflow_s): New symbol variable.
(obj_print_impl): Call gc_stack_check to protect recursive
printing againts overflow.
* lib.h (stack_overflow_s): Declared.
* unwind.c (uw_init): Register stack-overflow symbol as a an
exception symbol subtyped from error.
(uw_unwind_to_exit_point): When dealing with an unhandled
exception, turn off the stack limit, so we can print the
messages without triggering it in a loop.
* vm.c (vm_execute_closure, vm_funcall_common): Insert
gc_stack_check to the top of the execution of every VM
function.
* txr.1: Documented.
* share/txr/stdlib/doc-syms.tl: Updated.
|
|
|
|
|
|
|
|
| |
* gc.c (call_finalizers_impl): We don't have to null out the
next pointer of the finalization entry in the loop and note
that we are not doing this for the nodes that are going back
into final_list. Rather, we null-terminate the found list at
the end of the loop, just like we do with the final list.
|
|
|
|
|
|
|
|
| |
* gc.c (gc_wrap): We must not set full_gc according to the
argument, but only set it to 1 if the argument requests
full GC. full_gc is set to 1 for some reason having to do with
correctness; only the garbage collector can reset full_gc
back to 0, otherwise incorrect behavior will ensue.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* METALICENSE: 2020 copyrights bumped to 2021. Added note
about SHA-256 routines from Colin Percival.
* LICENSE, LICENSE-CYG, 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, lex.yy.c.shipped,
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/copy-file.tl, share/txr/stdlib/debugger.tl,
share/txr/stdlib/defset.tl, share/txr/stdlib/doloop.tl,
share/txr/stdlib/each-prod.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/quips.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, time.c, time.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,
y.tab.c.shipped: Copyright year bumped to 2021.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* gc.c (prepare_finals): Do not move unreachable objects with
finalizers into generation 0 here.
(call_finalizers_impl): Don't test the object for being in
generation 0; that may not be true since we don't ensure that
in prepare_finals now. Instead check he reachable flag of he
finalization entry; that tells us that we are dealing with an
object that had been found unreachable. When we re-introduce
it into freshobj, we set its generation to zero. Also, don't
bother with this freshobj logic if the full_gc flag has
been set. That now includes not bothering to set object
generations to zero.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* gc.c (call_finalizers_impl): Iterate over the finalizer
registrations until no more finalizers are identified,
performing additional rounds, as necessary. Thus if finalizers
register more finalizers that are eligible for processing
according to the criteria of he current phase, those are done
in the current phase.
(gc_finalize): We must now carefully set the reachable flag to
1 for a new finalization entry. This was always the right
thing to do and is logically correct: if an object is being
passed to finalize, it is necessarily reachable. Leaving the
0 initialization would do bad things now, as follows. If any
object whatsoever has a finalizer registered against it during
GC-driven finalization, its finalizer will be called. This is
bad if the object isn't garbage. Secondly, the object may be
moved into generation 0, and put into the freshobj list. This
is extremely bad if the object is reachable by generation 1
objects, which is now a wrong-way reference.
* txr.1: Updated.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
With the finalization count, we don't have to scan the
freshobj array for duplicates when calling finalizers.
However, the limited range of the counter limits how many
times we can register a finalizer against an object.
* gc.c (make_obj): Reset the new fincount field to zero
for a newly minted object.
(call_finalizers_impl): Decrement the fincount for
each object. Only run the freshobj-related logic when
the count hits zero.
(gc_finalize): Bump the fincount of a registered object. If
the counter overflows, throw an exception.
* lib.h (obj_common): Add new field fincount for the
finalization count.
* tree.c (tr_rebuild): Fix up dummy object initializer
to accommodate the new member.
* txr.1: Document that there is a limit on the number
of times an object can be registered for finalization.
|
|
|
|
|
|
|
|
|
| |
* gc.c (call_finalizers_impl): Objects are only added to
freshobj if they are in the zero generation. We should skip
that entire block of code if the object isn't in that
generation. Not only is it wasteful to execute that code for
the mature generation, but the logic falsely sets the full_gc
flag whenever processing a non-gen-0 object!
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This problem was introduced on Feb 18, 2019 in commit
3931df5cba3d826511503ad1c0a5b84c1363765e.
Explicit finalization of objects outside of GC can
trigger an assertion in a later GC pass.
* gc.c (call_finalizers_impl): We simply must not have
duplicate entries in fresh_obj; this causes problems for
sweep_one. Under Valgrind debugging, sweep_one protects the
memory of processed entries, so a duplicate visit triggers bad
accesses. A more serious issue is that this function can be
called outside of gc, explicitly, since it is available as an
API function. So that is to say, non-garbage objects can have
their finalizers called ouside of GC. If this function is
called explicitly, outside of GC, it can end up doing
something stupid, like adding a generation 1 object into the
freshobj array, triggering an assert. We address this by not
doing any of that processing if GC is not taking place.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The c_num and c_unum functions now take a self argument for
identifying the calling function. This requires changes in a
large number of places.
In a few places, additional functions acquire a self
argument. The ffi module has the most extensive example of
this.
Some functions mention their name in a larger string, or have
scattered literals giving their name; with the introduction of
the self local variable, these are replaced by references to
self.
In the following changelog, the notation TS stands for "take
self argument", meaning that the functions acquires a new "val
self" argument. The notation DS means "define self": the functions
in question defines a self variable, which they pass down.
The notation PS means that the functions pass down an existing
self variable to functions that now require it.
* args.h (args_count): TS.
* arith.c (c_unum, c_num): TS.
(toint, exptv): DS.
* buf.c (buf_check_len, buf_check_alloc_size, buf_check_index,
buf_do_set_len, replace_buf, buf_put_buf, buf_put_i8,
buf_put_u8, buf_put_char, buf_put_uchar, buf_get_bytes,
buf_get_i8, buf_get_u8, buf_get_cptr,
buf_strm_get_byte_callback, buf_strm_unget_byte, buf_swap32,
str_buf, buf_int, buf_uint, int_buf, uint_buf): PS.
(make_duplicate_buf, buf_shrink, sub_buf, buf_print,
buf_pprint): DS.
* chskum.c (sha256_stream_impl, sha256_buf, crc32_buf,
md5_stream_impl, md5_buf): TS.
(chksum_ensure_buf, sha256_stream, sha256, sha256_hash,
md5_stream, md5, md5_hash): PS.
(crc32_stream): DS.
* combi.c (perm_while_fun, perm_gen_fun_common,
perm_str_gen_fun, rperm_gen_fun, comb_vec_gen_fun,
comb_str_gen_fun, rcomb_vec_gen_fun, rcomb_str_gen_fun): DS.
* diff.c (dbg_clear, dbg_set, dbg_restore): DS.
* eval.c (do_eval, gather_free_refs, maprodv, maprendv,
maprodo, do_args_apf, do_args_ipf): DS.
(op_dwim, me_op, map_common): PS.
(prod_common): TS.
* ffi.c (struct txr_ffi_type): release member TS.
(make_ffi_type_pointer): PS and release argument TS.
(ffi_varray_dynsize, ffi_array_in, ffi_array_put_common,
ffi_array_get_common, ffi_varray_in, ffi_varray_null_term): PS.
(ffi_simple_release, ffi_ptr_in_release, ffi_struct_release,
ffi_wchar_array_get, ffi_array_release_common,
ffi_array_release, ffi_varray_release): TS.
(ffi_float_put, double_put, ffi_be_i16_put, ffi_be_u16_put,
ffi_le_i16_put, ffi_le_u16_put, ffi_be_i32_put, ffi_be_u32_put,
ffi_le_i32_put, ffi_sbit_put, ffi_ubit_put, ffi_buf_d_put,
make_ffi_type_array, make_ffi_type_enum, ffi_type_compile,
make_ffi_type_desc, ffi_make_call_desc, ffi_call_wrap,
ffi_closure_dispatch_save, ffi_put_into, ffi_in, ffi_get,
ffi_put, carray_set_length, carray_blank, carray_buf,
carray_buf_sync, carray_cptr, carray_refset, carray_sub,
carray_replace, carray_uint, carray_int): PS.
(carray_vec, carray_list): DS.
* filter.c (url_encode, url_decode, base64_stream_enc_impl): DS.
* ftw.c (ftw_callback, ftw_wrap): DS.
* gc.c (mark_obj, gc_set_delta): DS.
* glob.c (glob_wrap): DS.
* hash.c (equal_hash, eql_hash, eq_hash, do_make_hash,
hash_equal, set_hash_traversal_limit, gen_hash_seed): DS.
* itypes.c (c_i8, c_u8, c_i16, c_u16, c_i32, c_u32, c_i64,
c_u64, c_short, c_ushort, c_int, c_uint, c_long, c_ulong): PS.
* lib.c (seq_iter_rewind): TS and becomes internal.
(seq_iter_init_with_info, seq_setpos, replace_str, less,
replace_vec, diff, isec, obj_print_impl): PS.
(nthcdr, equal, mkstring, mkustring, upcase_str, downcase_str,
search_str, sub_str, cat_str, scat2, scat3, fmt_join,
split_str_keep, split_str_set, trim_str, int_str, chr_int,
chr_str, chr_str_set, vector, vecref, vecref_l, list_vec,
copy_vec, sub_vec, cat_vec, lazy_str_put, lazy_str_gt,
length_str_ge, length_str_lt, length_str_le, cptr_size_hint,
cptr_int, out_lazy_str, out_quasi_str, time_string_local_time,
time_string_utc, time_fields_local_time, time_fields_utc,
time_struct_local, time_struct_utc, make_time, time_meth,
time_parse_meth): DS.
(init_str, cat_str_init, cat_str_measure, cat_str_append,
vscat, time_fields_to_tm, time_struct_to_tm, make_time_impl): TS.
* lib.h (seq_iter_rewind): Declaration removed.
(c_num, c_unum, init_str): Declarations updated.
* match.c (LOG_MISMATCH, LOG_MATCH): PS.
(h_skip, h_coll, do_output_line, do_output, v_skip, v_fuzz,
v_collect): DS.
* parser.c (parser, circ_backpatch, report_security_problem,
hist_save, repl, lino_fileno, lino_getch, lineno_getl,
lineno_gets, lineno_open): DS.
(parser_set_lineno, lisp_parse_impl): PS.
* parser.l (YY_INPUT): PS.
* rand.c (make_random_state): PS.
* regex.c (print_rec): DS.
(search_regex): PS.
* signal.c (kill_wrap, raise_wrap, get_sig_handler,
getitimer_wrap, setitimer_wrap): DS.
* socket.c (addrinfo_in, sockaddr_pack, fd_timeout,
to_connect, open_sockfd, sock_mark_connected,
sock_timeout): TS.
(getaddrinfo_wrap, dgram_set_sock_peer, sock_bind,
sock_connect, sock_listen, sock_accept, sock_shutdown,
sock_send_timeout, sock_recv_timeout, socketpair_wrap): DS.
* stream.c (generic_fill_buf, errno_to_string, stdio_truncate,
string_out_put_string, open_fileno, open_command, base_name,
dir-name): DS.
(unget_byte, put_buf, fill_buf, fill_buf_adjust,
get_line_as_buf, formatv, put_byte, test_set_indent_mode,
test_neq_set_indent_mode, set_indent_mode, set_indent,
inc_indent, set_max_length, set_max_depth, open_subprocess, run ): PS.
(fds_subst, fds_swizzle): TS.
* struct.c (make_struct_type, super, umethod_args_fun): PS.
(method_args_fun): DS.
* strudel.c (strudel_put_buf, strudel_fill_buf): DS.
* sysif.c (errno_wrap, exit_wrap, usleep_wrap, mkdir_wrap,
ensure_dir, makedev_wrap, minor_wrap, major_wrap, mknod_wrap,
mkfifo_wrap, wait_wrap, wifexited, wexitstatus, wifsignaled,
wtermsig, wcoredump, wifstopped, wstopsig, wifcontinued,
dup_wrap, close_wrap, exit_star_wrap, umask_wrap, setuid_wrap,
seteuid_wrap, setgid_wrap, setegid_wrap,
simulate_setuid_setgid, getpwuid_wrap, fnmatch_wrap,
dlopen_wrap): DS.
(chmod_wrap, do_chown, flock_pack, do_utimes, poll_wrap,
setgroups_wrap, setresuid_wrap, setresgid_wrap, getgrgid_wrap): PS.
(c_time): TS.
* sysif.h (c_time): Declaration updated.
* syslog.c (openlog_wrap, syslog_wrap): DS.
* termios.c (termios_pack): TS.
(tcgetattr_wrap, tcsetattr_wrap, tcsendbreak_wrap,
tcdrain_wrap, tcflush_wrap, tcflow_rap, encode_speeds,
decode_speeds): DS.
* txr.c (compato, array_dim, gc_delta): DS.
* unwind.c (uw_find_frames_by_mask): DS.
* vm.c (vm_make_desc): PS.
(vm_make_closure, vm_swtch): DS.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
I've noticed that the January 9, 2020 commit "gc: obtain stack top using
alloca" triggers spurious retention when compiling with HAVE_VALGRIND.
The finalization test case tests/012/fini.tl breaks because the expected
finalizers are not called. Changing the (sys:gc) call to two calls to
(sys:gc 1) makes it pass.
The culprit seems to be the inlining of the complex function sweep
into gc. It has local variables for which spaces has to be reserved,
which are not used until after mark() is called; likely the values
in those spaces are picked up by the stack scan.
Let's make sure that functions called out of gc() are not inlined.
* gc.c (mark, sweep, prepare_finals, call_finals): Mark NOTINLINE.
|
|
|
|
|
|
|
|
|
|
| |
Time for some spring cleaning.
* args.c, arith.c, buf.c, cadr.c, chksum.c, debug.c, ftw.c,
gc.c, gencadr.txr, glob.c, hash.c, lisplib.c, match.c,
parser.c, parser.l, parser.y, rand.c, signal.c, stream.c,
strudel.c, syslog.c, tree.c, unwind.c, utf8.c, vm.c: Numerous
unnecessary #include directives removed.
|
|
|
|
|
|
|
|
| |
* gc.c (gc_wrap): Takes argument for requesting full garbage
collection.
(gc_late_init): Update registration of gc intrinsic.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This is the first round of an effort to enable GCC's -Wextra
option. All function parameters that are unused an that we
cannot eliminate are treated with a cast to void in the
function body.
* args.c (args_key_check_store): Cast unused param to void.
* combi.c (perm_list_gen_fill): Likewise.
* eval.c (op_error, op_meta_error, op_quote op_qquote_error,
op_unquote_error, op_load_time_lit, me_each, me_for,
me_quasilist, me_flet_labels, hash_min_max, me_ignerr,
me_whilet, me_iflet_whenlet, me_dotimes, me_mlet,
me_load_time, me_load_for): Likewise.
* ffi.c (ffi_void_put, ffi_fixed_dynsize, *ffi_fixed_alloc,
ffi_noop_free, ffi_void_get, ffi_simple_release, ffi_i8_put,
ffi_i8_get, ffi_u8_put, ffi_u8_get, ffi_i16_put, ffi_i16_get,
ffi_u16_put, ffi_u16_get, ffi_i32_put, ffi_i32_get,
ffi_u32_put, ffi_u32_get, ffi_i64_put, ffi_i64_get,
ffi_u64_put, ffi_u64_get, ffi_char_put, ffi_char_get,
ffi_uchar_put, ffi_uchar_get, ffi_bchar_get, ffi_short_put,
ffi_short_get, ffi_ushort_put, ffi_ushort_get, ffi_int_put,
ffi_int_get, ffi_uint_put, ffi_uint_get, ffi_long_put,
ffi_long_get, ffi_ulong_put, ffi_ulong_get, ffi_float_put,
ffi_float_get, ffi_double_put, ffi_double_get, ffi_val_put,
ffi_val_get, ffi_be_i16_put, ffi_be_i16_get, ffi_be_u16_put,
ffi_be_u16_get, ffi_le_i16_put, ffi_le_i16_get,
ffi_le_u16_put, ffi_le_u16_get, ffi_be_i32_put,
ffi_be_i32_get, ffi_be_u32_put, ffi_be_u32_get,
ffi_le_i32_put, ffi_le_i32_get, ffi_le_u32_put,
ffi_le_u32_get, ffi_be_i64_put, ffi_be_i64_get,
ffi_be_u64_put, ffi_be_u64_get, ffi_le_i64_put,
ffi_le_i64_get, ffi_le_u64_put, ffi_le_u64_get, ffi_wchar_put,
ffi_wchar_get, ffi_sbit_get, ffi_ubit_get, ffi_cptr_get,
ffi_str_in, ffi_str_put, ffi_str_get, ffi_str_d_get,
ffi_wstr_in, ffi_wstr_get, ffi_wstr_put, ffi_wstr_d_get,
ffi_bstr_in, ffi_bstr_put, ffi_bstr_get, ffi_bstr_d_get,
ffi_buf_in, ffi_buf_put, ffi_buf_get, ffi_buf_d_in,
ffi_buf_d_put, ffi_buf_d_get, ffi_closure_put, ffi_ptr_in_in,
ffi_ptr_in_d_in, ffi_ptr_in_out, ffi_ptr_out_in,
ffi_ptr_out_out, ffi_ptr_out_null_put, ffi_ptr_out_s_in,
ffi_flex_struct_in, ffi_carray_get, ffi_union_get,
make_ffi_type_builtin, make_ffi_type_array,
ffi_closure_dispatch, ffi_closure_dispatch_safe): Likewise.
* gc.c (cobj_destroy_stub_op, cobj_destroy_free_op, cobj_mark_op): Likewise.
* lib.c (seq_iter_get_nil, seq_iter_peek_nil): Likewise.
* linenoise/linenoise.c (sigwinch_handler): Likewise.
* parser.c (repl_intr, read_eval_ret_last, repl_warning,
is_balanced_line): Likewise.
* parser.y (yydebug_onoff): Likewise.
* socket.c (dgram_close): Likewise.
* stream.c (unimpl_put_string, unimpl_put_char,
unimpl_put_byte, unimpl_unget_char, unimpl_unget_byte,
unimpl_put_buf, unimpl_fill_buf, unimpl_seek, unimpl_truncate,
unimpl_set_sock_peer, null_put_string, null_put_char,
null_put_byte, null_get_line, null_get_char, null_get_byte,
null_close, null_flush, null_seek, null_set_prop,
null_get_error, null_get_error_str, null_clear_error,
null_get_fd, dir_close): Likewise.
* struct.c (struct_type_print): Likewise.
* unwind.c (me_defex): Likewise.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
An object of args type captures into the heap the "struct
args" argument list that normally appears only on the stack.
Such an object also has space for a car and cdr field,
which can come in handy.
* args.c (dyn_args): New function: hoist a struct args *
into an args heap object.
* args.h (dyn_args): Declared.
* gc.c (finalize, mark_obj): Handle DARGS type code.
* hash.c (equal_hash): Handle DARG via eq equivalence.
* lib.c (args_s): New symbol variable.
(code2type): Map DARG to args symbol.
(equal): Handle DARG type, using eq equivalence for now.
(obj_init): Initialize args_s with interned symbol.
* lib.h (enum type, type_t): New type code, DARG.
(struct dyn_args): New struct.
(union obj): New member, a of type struct dyn_args.
* txr.1: Documented args type under typeof.
|
|
|
|
|
|
|
|
|
|
|
| |
* configure (small_mem): New variable. Provide help text and
show default value of --small-mem option. Generate
CONFIG_SMALL_MEM in config.h.
* gc.c (HEAP_SIZE, CHECKOBJ_VEC_SIZE, MUTOBJ_VEC_SIZE,
FULL_GC_INTERVAL, FRESHOBJ_VEC_SIZE, DFL_MALLOC_DELTA_THRESH):
Define conservative values of these constants if
CONFIG_SMALL_MEM is in effect.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.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.
|
|
|
|
|
| |
* gc.c (STACK_TOP_EXTRA_WORDS): Changing from 4 to 12
eliminates crashes.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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.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.
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.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.c (mark_obj): Remove material excluded by #if 1.
(gc): Eliminate #if 0 block.
|