Commit graph

8925 commits

Author SHA1 Message Date
Daniel Kochmański
1866b3a24e xxx 2025-05-26 18:55:30 +02:00
Daniel Kochmański
71763174ef doc: clarify wording for :INITIAL-BINDINGS in MAKE-PROCESS 2025-05-26 09:28:10 +02:00
Daniel Kochmański
b1605eaeae update the changelog 2025-05-26 09:28:10 +02:00
Daniel Kochmański
5233c2104a stacks: move ECL_STACK_RESIZE_DISABLE_INTERRUPTS before realloc 2025-05-26 09:28:10 +02:00
Daniel Kochmański
ecaa73155b cleanup: reorganize cl_env_struct 2025-05-26 09:28:10 +02:00
Daniel Kochmański
7dfc7ac5e9 stacks: add a general purpose stack implementation based on vector 2025-05-26 09:28:10 +02:00
Daniel Kochmański
03e9f9296c stacks: refactor file to separate low level and high level operators
With this it will possible to move low level primitives earlier in the bootstrap
process.
2025-05-26 09:28:08 +02:00
Daniel Kochmański
fd2fae1a39 stacks: merge stack overflow errors into a single handler
Replace calls to cl_error and cl_cerror with CEstack_overflow.
2025-05-26 09:21:50 +02:00
Daniel Kochmański
21c23973ae stacks: refactor the code in stacks.d
- {run,bds,frs}_set_size functions were very similar; I've updated them to
  follow the same naming convention and execution order to indicate that.
- these functions are now renamed to xxx_set_limit -that simplifies some code
- there were inconsistencies in how we've treated boot sizes (limit vs size)
2025-05-26 09:21:32 +02:00
Daniel Kochmański
72fb1c583a stacks: remove serror, stack-error-handler and reset-margin
All these operations were propagated up to the condition system in order to
reset the stack margin in the case of a non-local exit. We can do that easily
with open-coded unwind protect within stacks.
2025-05-26 08:44:18 +02:00
Daniel Kochmański
6463cae89c stacks: rename bindings and runtime stack pointers stored in frs
They are named to follow the same convention hinting that it is an index, not a
pointer.
2025-05-26 08:43:59 +02:00
Daniel Kochmański
7db0a89f42 stacks: use a manual allocator for stacks
Objects have a well defind extent so there is no need to rely on GC for
them. This change allows us to move stack initialization before garbage
collector is introduced into the system (or even without any GC).
2025-05-26 08:37:06 +02:00
Daniel Kochmański
1b058f0e3a stacks: manually allocate bindings table
This commit removes initial bindings array from the process and allocates it
only in the bds stack. To make fields in the structure less confusing we rename
initial_bindings slot to inherit_bindings_p.

On observable behavior change is that bindings are inherited when the process is
enabled, not when it is created. That was not specified in documentation so it
should be fine to change this behavior. Moreover it makes more sense from the
programmer perspective -- we want to inherit bindings of the process that starts
our thread, not the one that creates it.
2025-05-26 08:36:03 +02:00
Daniel Kochmański
0a8de3f234 stacks: make runtime stack accessors inline functions
Also remove an unused operator FEstack_advance. Macro definition names do not
change and they expand (when appropriate) to the inline function.

New function names refer to data_stack, while upcased macro names mentions only
the STACK. This is in line with how forth refers to the data stack when it is
not ambiguous.
2025-05-26 08:34:06 +02:00
Daniel Kochmański
51157bbf9d stacks: move runtime stack to a separate structure 2025-05-26 07:43:41 +02:00
Daniel Kochmański
45f3be3aa1 stacks: move C shadow stack to a separate structure 2025-05-26 07:43:41 +02:00
Daniel Kochmański
593d9d2190 stacks: move invocation history stack to a separate structure 2025-05-26 07:43:41 +02:00
Daniel Kochmański
9687a1d33a stacks: move frames stack to a separate structure 2025-05-26 07:43:41 +02:00
Daniel Kochmański
326a914fff stacks: clean up inlined versions for bds operators
We remove defines in favor of 'static inline' that is available in all c99
compilers. Previously it was specialcased only for GNUC.
2025-05-26 07:43:41 +02:00
Daniel Kochmański
8f00f3494a stacks: rename thread_local_bindings{,_size} to tl_bindings{,_size}
This is strictly cosmetic change.
2025-05-26 07:43:41 +02:00
Daniel Kochmański
f365ebe079 stacks: move the binding stack to a separate structure 2025-05-26 07:43:41 +02:00
Marius Gerbershagen
0f6116081c ecl_to_int64_t: fix typo
Introduced by the refactor in commit 1102e58e0e
2025-05-25 17:13:57 +02:00
Daniel Kochmański
c0720610dd tests: add missing imports and tweak mix.0010.file-stream-fd
We didn't export *TEST-NAME*, FAILED and TEST-FAILURE from 2am-ecl, so the macro
FAIL did not work correctly.

The test mix.0010.file-stream-fd contained a safeguard for a bug from 2016, no
need to guard against that today.
2025-05-23 08:15:00 +02:00
Daniel Kochmański
09622435bc core: fix a race condition between core symbols and the gc
The GC is enabled when we create initial symbols. The function make_this_symbol
initializes symbols from a static table as follows:

1. initialize symbol structure fields
2. associate the symbol with its package
3. associate the symbol with its function
4. increment cl_num_symbols_in_core

Most notably in point 2:
s->symbol.name = ecl_make_constant_base_string(name,-1);

GC's stacks_scanner marks

  [cl_symbols; cl_symbols+cl_num_symbols_in_core]

in other words, if the GC kicks in between 1. and 4., the symbol name may be
garbage collected, messing the symbol name and package exports.

To mitigate that, we assign intermediate values on the stack and increment
the number of symbols in core after the symbol is initialized:

1. store initialization values on stack -- cl_object foo = alloc();
2. initialize symbol structure fields
3. increment cl_num_symbols_in_core
4. associate the symbol with its package and function
2025-05-20 13:57:21 +02:00
Daniel Kochmański
9d8394f0cd bytevm: when unbinding locals don't keep the unbound reference
Since the stack frame is always marked fully, decrementing the pointer keeps a
reference to the unbound object effectively preventing its garbage collection
until it is overwritten by another binding or the stack is closed.
2025-05-14 10:52:45 +02:00
Daniel Kochmański
62c8f3f714 threads: get rid of an annoying warning stemming from xopen
We've defined _XOPEN_SOURCE 600 but glibc defines it as 700 or more.
2025-05-13 14:18:10 +02:00
Marius Gerbershagen
a01603a04a Merge branch 'bytevm-locals-on-stack' into 'develop'
ByteVM locals are stored on the lisp stack

See merge request embeddable-common-lisp/ecl!346
2025-05-10 17:31:24 +00:00
Daniel Kochmański
1b5a03ffca tests: disable a test on bytecmp that uses compiler-cc 2025-05-09 13:55:59 +02:00
Daniel Kochmański
db9f22c190 lisp stack: deallocate the old stack after resizing
Just like with other stacks we call ecl_dealloc on the old stack. Previously
we had stack frames that could have referenced it, but we can treat it like
other stacks, because there are not lingering references.
2025-05-09 13:55:59 +02:00
Daniel Kochmański
2f9ce70e8f stack frames: dereference directly to env->stack
Previously we've cached the stack base and dereferenced from there, but when the
stack is resized, this reference is invalidated and there is no good fix it in
all frames (we don't store back references).

This commit replaces pointers with indexes, so the stack frame is always
displaced onto the current lisp stack.
2025-05-09 13:55:59 +02:00
Daniel Kochmański
293f93b425 stack frames: don't displace onto env->values vector
ad6f1f7f10 (2008-05-12) allowed for displacing
stack frames onto the values vector. This commit seems to be before we've stored
them on lisp stack.

As for the rationale why we revert that change:

1. There may be a slight performance improvement because the standard gf
dispatch won't be forced to copy the stack frame

2. Stack frame operators assume that they are displaced onto env->stack*, for
example ecl_stack_frame_push increments env->stack_top

3. If we fully buy into assumption that the stack frame is displaced onto
env->stack* then we may replace pointers with indexes and protect the user from
accessing invalidated memory when the stack grows

The last point will be implemented in the next commit. It is worth noting, that
frames auto-heal themselves if their own operation is the cause of the stack
growth, but all other stack frames are left invalid after the operation.
2025-05-09 13:55:59 +02:00
Daniel Kochmański
aefcd77e02 tests: add a regression test for an encountered issue
This issue was never manifestable in develop branch.
2025-05-09 13:55:59 +02:00
Daniel Kochmański
fdf7c77909 bytevm: faster closure creation and less consing
OP_FLET previously had to first create functions referencing the env "before"
and then add these functions to the env "after". This is because we were
addressing from the stack top:

  env: bottom[0:var]top
  fn1: ref(top-1)
  fn2: ref(top-1)
  env: bottom[0:var, 1:fn1, 2:f2n]top

Otherwise fn2 referencing top-1 would point to fn1 instead of var.

Now that locals are addressed from the stack bottom we can add functions eagerly
to locals without consing intermediate sequence of functions:

  env: bottom[0:var]top
  fn1: ref(bottom+0)
  env: bottom[0:var, 1:fn1]top
  fn2: ref(bottom+0)
  env: bottom[0:var, 1:fn1, 2:f2n]top

That saves us one loop (nfun iterations).

A similar observation applies to LABELS, although we still need the closure
fixup because earlier function may reference a function defined later, so we
still need a second loop. That said we don't have to cons a separate sequence of
functions, because we may iterate over locals vector instead.

Both changes save us from an operator that adds a collection to the lcl_env, so
we remove tack_lcl macro and its expansion function foot_lcl.
2025-05-09 13:55:59 +02:00
Daniel Kochmański
0bf83ad30c bytevm: allocate locals on the stack
This should speed things up as well as reduce consing. To be verified.
2025-05-09 13:55:59 +02:00
Daniel Kochmański
2382fa41ab bytecmp: track the maximal size of the locals environment
After the function is compiled we assign the width to nlcl. This will be used to
determine the necessary size of the stack frame for locals.
2025-05-09 13:55:59 +02:00
Daniel Kochmański
512a31301d bytecmp: [unbug] remove assertions that are now not necessary 2025-05-09 13:55:59 +02:00
Daniel Kochmański
16996f8d38 bytevm: treat blocks and tags as normal local bindings
Previously when unbinding we've skipped blocks and tags and let the frame exit
to collect the frame variable. This commit simplifies managing the environment
in the compiler.
2025-05-09 13:55:59 +02:00
Daniel Kochmański
878fc3441c bytecmp: compute the locals env size correctly
Previously our calculations were off because:

- we've counted special variables
- we didn't decrement the env size when unbound

One could argue that we need only to increment it, but then we'd end up with the
size too big. Consider:

(progn
 (let ((a 1)) (foobar))
 (let ((b 1)) (foobar)))

In this snippet we have two local variables, but we never look at locals beyond
the first element.
2025-05-09 13:55:59 +02:00
Daniel Kochmański
6babf49b1c bytevm: reshape OP_FRAME to resemble OP_TAGBODY and OP_PROTECT
This is a cosmetic change that makes unwinding look similar across operators.
2025-05-09 13:55:59 +02:00
Daniel Kochmański
8bc957d88f bytecmp: [debug] add assertions for the current environment size
env_size is not computed correctly (neither max size nor current size), these
assertions are meant to help with mending the issue in order to correctly
determine the size of the locals environment.
2025-05-09 13:55:59 +02:00
Daniel Kochmański
600901da05 bytecodes: add a new slot nlcl denoting the maximal number of locals
Currently it is initialized to NIL, the next commit will assign to it a correct
value.
2025-05-09 13:55:59 +02:00
Daniel Kochmański
9addb2cc4a bytevm: access interpreter locals in fifo order
This is a preliminary step before replacing a structure consed on a heap with
the lisp stack.
2025-05-09 13:55:59 +02:00
Daniel Kochmański
34f546027f compiler: factor the local entry index into a function
c_lcl_idx computes the location of the entry in the locals env. It does traverse
the list again, so it adds a little overhead, but this will allow us to
customize it later to compute a location from the bottom.
2025-05-09 13:55:59 +02:00
Daniel Kochmański
c2d1a0c2d2 ecl_interpreter: abstract away all lcl accessors
We are going to change the representation of the local environment, but first we
make identify accessors and put them behind macros.

While doing so the OP_LABELS has been changed to look similar to OP_FLET. Among
other things we cons separately functions into fun_env, but this inefficiency
will be removed later when we address local entries from the frame.base.
2025-05-09 13:55:59 +02:00
Daniel Kochmański
a44a74a3f4 internal: ignore array-bounds errors on GCC >= 12
As noted in the comment, GCC 12.0 onwards generates an invalid warning about
array bounds when we cast a stack allocated object to cl_object and use it

    warning: array subscript ‘union cl_lispunion[0]’ is partly outside array
    bounds of ‘struct ecl_stack_frame[1]’ [-Warray-bounds=]

The code is conforming, but apparently GCC IR has generated a dead branch that
accesses the array out of bounds. For time being we disable this warning.

See also:
https://gitlab.com/libeigen/eigen/-/issues/2506
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106274
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105523

and generally explroe gcc bugzilla for this kind of false positive.
2025-05-09 13:55:59 +02:00
Daniel Kochmański
2948a57174 interpreter: fix a braino
During recent refactor we've dereferenced a frame instaed of bytecodes.
2025-05-09 12:12:05 +02:00
Daniel Kochmański
885e53a0b5 serialize: fix a braino
ecl_frame was used instead of ecl_stack_frame to compute the size of t_frame.
2025-05-09 12:12:05 +02:00
Daniel Kochmański
895f9571c3 symbols: initialize .macfun field
Apparently this one was missing.
2025-05-05 10:26:51 +02:00
Marius Gerbershagen
f69ded9777 remove bogus #undef bool statement
Not sure why that was ever there.
2025-05-04 18:02:59 +02:00
Marius Gerbershagen
b4e22b1854 fix typo 2025-05-04 17:52:50 +02:00