* gpgscm/scheme.c (gc_reservation_failure): Fix adding ";".
[!NDEBUG] (scheme_init_custom_alloc): Don't init seserved_lineno.
--
Picked from libgpg-error commit of:
8a9397896fd202dcfb3fb46259e43bc05a0ddd2e
In some build environment, NDEBUG is defined (although it's
bad practice). This change supports such a situation.
GnuPG-bug-id: 3959
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
* tests/gpgscm/scheme.c (CASE): Use unused attribute for GCC > 6.
(FALLTHROUGH): New for fallthrough.
(Eval_Cycle): Use FALLTHROUGH. Remove not-needed comment of
fallthrough.
--
Since GCC combines C preprocessor macro expansion, the fallthrough
comment doesn't work well to suppress warnings for
-Wimplicit-fallthrough, near the macro CASE. To handle this
problem, we use GCC's extension of unused label and fallthrough
attributes.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
* tests/gpgscm/scheme.c (CASE): Rearrange so that the case statement
is at the front.
(Eval_Cycle): Improve fallthrough annotations.
Signed-off-by: Justus Winter <justus@g10code.com>
* tests/gpgscm/scheme-private.h (struct scheme): New field
'frame_freelist'.
* tests/gpgscm/scheme.c (enum scheme_types): New type 'T_FRAME'.
(type_to_string): Handle new type.
(settype): New macro.
(gc_disable): Make sure there is at least one frame in the free list.
(mark): Handle frame objects.
(finalize_cell): Likewise.
(dump_stack_initialize): Initialize free list.
(dump_stack_free): Simplify.
(frame_length): New variable.
(dump_stack_make_frame): New function.
(frame_slots): Likewise.
(frame_payload): New macro.
(dump_stack_allocate_frame): New function.
(dump_stack_deallocate_frame): Likewise.
(dump_stack_preallocate_frame): Likewise.
(_s_return): Unpack frame object and deallocate it.
(s_save): Wrap state in an frame object.
(dump_stack_mark): Mark the free list.
--
TinySCHEME being a SECD-machine needs to push frames onto the dump
stack. Previously, the dump stack was a list. This required four
cells for the spine, as well as up to one additional cell to encode
the current opcode. This was quite inefficient despite the fact that
we recovered the spine as well as the integer cell.
We introduce frame objects, which are a special variant of vectors of
length four. Since the length is fixed, this frees up the length
field of the vector object to store the unboxed opcode. A frame
object now fits in two cells.
Saving two or three cells is a mere byproduct, the performance gain
comes from increased locality, unboxed opcode representation, and the
ability to easily put the objects in a free list, keeping the garbage
collector out of the continuous motion of the virtual machine.
Signed-off-by: Justus Winter <justus@g10code.com>
* tests/gpgscm/scheme-private.h (struct scheme): Remove field 'op'.
* tests/gpgscm/scheme.c (opexe_0): Inline into 'Eval_Cycle'.
(_Error_1): Return the opcode to evaluate next.
(Error_1): Do not return, but set the opcode and goto dispatch.
(Error_0): Likewise.
(s_goto): Likewise.
(s_return): Likewise.
(s_return_enable_gc): Likewise.
(s_thread_to): Remove superfluous cast.
(_s_return): Return the opcode to evaluate next.
(scheme_init_custom_alloc): Adapt to removal of field 'op'.
Signed-off-by: Justus Winter <justus@g10code.com>
* tests/gpgscm/scheme.c (finalize_cell): Use switch, return whether
the cell may be freed.
(gc): Update callsite.
Signed-off-by: Justus Winter <justus@g10code.com>
* tests/gpgscm/scheme-private.h (CELL_MINRECOVER): New macro.
* tests/gpgscm/scheme.c (_get_cell): Move the heuristic to get more
cells...
(gc): ... here where every caller benefits from the optimization.
Signed-off-by: Justus Winter <justus@g10code.com>
* tests/gpgscm/scheme.c (opexe_0): Consider 'op', not 'sc->op'. The
former is the opcode we are currently executing.
Signed-off-by: Justus Winter <justus@g10code.com>
* tests/gpgscm/main.c (load): Try to mmap the script.
* tests/gpgscm/scheme.c (scheme_load_memory): New function, a
generalization of 'scheme_load_string'.
* tests/gpgscm/scheme.h (scheme_load_memory): New prototype.
Signed-off-by: Justus Winter <justus@g10code.com>
* tests/gpgscm/scheme.c (op_code_info): Fix type, add forward
declaration.
(check_arguments): New function.
(Eval_cycle): Use the new function.
Signed-off-by: Justus Winter <justus@g10code.com>
* tests/gpgscm/opdefines.h: Make tags mandatory.
* tests/gpgscm/scheme.c: Likewise.
* tests/gpgscm/scheme.h: Likewise.
--
Tags provide a constant-time lookup mechanism for almost every object.
This is useful for the interpreter itself, and the code for tags is
tiny.
Signed-off-by: Justus Winter <justus@g10code.com>
* tests/gpgscm/scheme.c (opexe_6): Merge into 'opexe_0'.
* tests/gpgscm/opdefines.h: Adapt.
--
Having separate functions to execute opcodes reduces our ability to
thread the code and prevents the dispatch_table from being moved to
rodata.
Signed-off-by: Justus Winter <justus@g10code.com>
* tests/gpgscm/scheme.c (opexe_5): Merge into 'opexe_0'.
* tests/gpgscm/opdefines.h: Adapt.
--
Having separate functions to execute opcodes reduces our ability to
thread the code and prevents the dispatch_table from being moved to
rodata.
Signed-off-by: Justus Winter <justus@g10code.com>
* tests/gpgscm/scheme.c (opexe_4): Merge into 'opexe_0'.
* tests/gpgscm/opdefines.h: Adapt.
--
Having separate functions to execute opcodes reduces our ability to
thread the code and prevents the dispatch_table from being moved to
rodata.
Signed-off-by: Justus Winter <justus@g10code.com>
* tests/gpgscm/scheme.c (opexe_3): Merge into 'opexe_0'.
* tests/gpgscm/opdefines.h: Adapt.
--
Having separate functions to execute opcodes reduces our ability to
thread the code and prevents the dispatch_table from being moved to
rodata.
Signed-off-by: Justus Winter <justus@g10code.com>
* tests/gpgscm/scheme.c (opexe_2): Merge into 'opexe_0'.
* tests/gpgscm/opdefines.h: Adapt.
--
Having separate functions to execute opcodes reduces our ability to
thread the code and prevents the dispatch_table from being moved to
rodata.
Signed-off-by: Justus Winter <justus@g10code.com>
* tests/gpgscm/scheme.c (opexe_1): Merge into 'opexe_0'.
* tests/gpgscm/opdefines.h: Adapt.
--
Having separate functions to execute opcodes reduces our ability to
thread the code and prevents the dispatch_table from being moved to
rodata.
Signed-off-by: Justus Winter <justus@g10code.com>
* tests/gpgscm/Makefile.am (gpgscm_SOURCES): Add new file.
* tests/gpgscm/scheme-private.h (struct cell): Move number to the top
of the union so that we can initialize it.
(struct scheme): Remove 'integer_segment'.
* tests/gpgscm/scheme.c (initialize_small_integers): Remove function.
(small_integers): New variable.
(MAX_SMALL_INTEGER): Compute.
(mk_small_integer): Adapt.
(mark): Avoid marking objects already marked. This allows us to run
the algorithm over objects in the rodata section if they are already
marked.
(scheme_init_custom_alloc): Remove initialization.
(scheme_deinit): Remove deallocation.
* tests/gpgscm/small-integers.h: New file.
--
Allocate small integers from a fixed pool in the rodata section. This
spares us the initialization, and deduplicates integers across
different processes. It also makes the integers immutable, increasing
memory safety.
Signed-off-by: Justus Winter <justus@g10code.com>
* tests/gpgscm/scheme-private.h (struct scheme): Make 'vptr' const.
* tests/gpgscm/scheme.c (num_zero): Statically initialize and turn
into constant.
(num_one): Likewise.
(charnames): Change type so that it can be stored in rodata.
(is_ascii_name): Adapt slightly.
(assign_proc): Make argument const char *.
(op_code_info): Make some fields const char *.
(tests): Make const.
(dispatch_table): Make const. At least it can be made read-only after
relocation.
(Eval_Cycle): Adapt slightly.
(vtbl): Make const.
Signed-off-by: Justus Winter <justus@g10code.com>
* tests/gpgscm/scheme-private.h (struct scheme): Remove fixed-size
arrays for cell segments, replace them with a pointer to the new
'struct cell_segment' instead.
* tests/gpgscm/scheme.c (struct cell_segment): New definition.
(_alloc_cellseg): Allocate the header within the segment, return a
pointer to the header.
(_dealloc_cellseg): New function.
(alloc_cellseg): Insert the segments into a list.
(_get_cell): Allocate a new segment if less than a quarter of
CELL_SIGSIZE is recovered during garbage collection.
(initialize_small_integers): Adapt callsite.
(gc): Walk the list of segments.
(scheme_init_custom_alloc): Remove initialization of removed field.
(scheme_deinit): Adapt deallocation.
--
Previously the number of cells that could be allocated was a
compile-time limit. Remove this limit.
Signed-off-by: Justus Winter <justus@g10code.com>
* tests/gpgscm/scheme.c (opexe_5): Do not modify the integer in-place
while printing an vector. Integer objects may be shared, so they must
not be mutated.
Signed-off-by: Justus Winter <justus@g10code.com>
* tests/gpgscm/scheme.c (get_vector_object): Initialize unused slots
at the end of vectors.
--
They should not be used for anything, but let's just initialize them
to something benign to be sure.
GnuPG-bug-id: 3014
Signed-off-by: Justus Winter <justus@g10code.com>
* tests/gpgscm/scheme.c (copy_value): New function.
(mk_tagged_value): Use new function.
(opexe_4): Likewise for OP_SAVE_FORCED.
--
Occasionally, we need to copy a value from one location in the storage
to another. Scheme objects are fine. Some primitive objects,
however, require finalization, usually to free resources.
For these values, we either make a copy or acquire a reference.
Fixes e.g. a double free if a delayed expression evaluating to a
string is forced.
Signed-off-by: Justus Winter <justus@g10code.com>
* tests/gpgscm/scheme.c (procnum): Procedures always have an integer
number, so we can safely use the cheaper 'ivalue_unchecked'.
Signed-off-by: Justus Winter <justus@g10code.com>
* tests/gpgscm/scheme.c (oblist_add_by_name): We now always get a
slot. Simplify accordingly.
(oblist_find_by_name): Always return the slot.
(vector_elem_slot): New function.
(new_slot_spec_in_env): We now always get a slot. Remove parameter
'env'. Simplify accordingly.
(find_slot_spec_in_env): Always return a slot.
(new_slot_in_env): Adapt callsite.
(opexe_0): Likewise.
(opexe_1): Likewise.
(scheme_define): Likewise.
--
Now that the ill-devised immediate values framework is gone, there is
no need to tag the pointers in vectors anymore. Therefore, we can
always return a pointer to the slot in the hash table lookup
functions.
Signed-off-by: Justus Winter <justus@g10code.com>
* tests/gpgscm/scheme.c (IMMEDIATE_TAG): Remove macro.
(is_immediate): Likewise.
(set_immediate): Likewise.
(clr_immediate): Likewise.
(enum scheme_types): Set the LSB in every value.
(fill_vector): Adapt.
(vector_elem): Likewise.
(set_vector_elem): Likewise.
(mark): Likewise.
(gc): Test for the LSB to tell typeflags apart from pointers stored in
the same memory location.
--
Supporting immediate values would require invasive changes to the
interpreter and is likely not worth the trouble. On the other hand,
tagging pointers in vectors complicated the hash table implementation
needlessly. Therefore, I remove this again.
This fixes a crash on big endian architectures.
GnuPG-bug-id: 2996
Signed-off-by: Justus Winter <justus@g10code.com>
* tests/gpgscm/scheme.c: Define local strlwr only when HAVE_STRLWR is
not defined in config.h.
* tests/gpgscm/scheme-config.h: Remove hack.
Signed-off-by: Justus Winter <justus@g10code.com>
* tests/gpgscm/scheme.c (port_increment_current_line): Avoid creating
the same integer if the delta is zero. This happens a lot during
parsing, and puts pressure on the memory allocator.
Signed-off-by: Justus Winter <justus@g10code.com>
* tests/gpgscm/scheme.c (opexe_5): Only increment the line number on
newlines.
Fixes-commit: 7cc57e2c63
Signed-off-by: Justus Winter <justus@g10code.com>
* tests/gpgscm/scheme-private.h (struct port): Move location
information out of the union.
* tests/gpgscm/scheme.c (mark): All ports need marking now.
(gc): Likewise all ports on the load stack.
(port_clear_location): Adapt accordingly. Also, add an empty function
for !SHOW_ERROR_LINE.
(port_increment_current_line): Likewise.
(port_reset_current_line): Drop function in favor of...
(port_init_location): ... this new function.
(file_push): Simplify.
(file_pop): Likewise.
(port_rep_from_filename): Likewise.
(port_rep_from_file): Likewise.
(port_rep_from_string): Also initialize the location.
(port_rep_from_scratch): Likewise.
(port_close): Simplify and generalize.
(skipspace): Likewise.
(token): Likewise.
(_Error_1): Generalize.
(opexe_5): Likewise.
(scheme_deinit): Simplify and generalize.
(scheme_load_named_file): Likewise.
(scheme_load_string): Also initialize the location.
--
This change tracks the location of source code loaded from non-file
ports that is used in error messages. It also simplifies the code
quite a bit.
Signed-off-by: Justus Winter <justus@g10code.com>
* tests/gpgscm/scheme.c (oblist_initial_value): Increase the size of
the hash table based on the number of symbols used after initializing
the interpreter.
(new_frame_in_env): Increase the size of the hash table based on the
number of variables in the global environement.
Signed-off-by: Justus Winter <justus@g10code.com>
* tests/gpgscm/scheme.c (pointercmp): New function.
(new_slot_spec_in_env): Add and use slot for insertions.
(find_slot_spec_in_env): New variant of 'find_slot_in_env' that
returns the slot on failures.
(find_slot_in_env): Express using the new function.
(new_slot_in_env): Update callsite.
(opexe_0): Optimize lookup-or-insert.
(opexe_1): Likewise.
(scheme_define): Likewise.
--
Optimize environment lookups by keeping the lists in the hash table or
the list sorted. Optimize the insertions by passing the slot computed
by the lookup to the insertion.
Signed-off-by: Justus Winter <justus@g10code.com>
* tests/gpgscm/scheme.c (oblist_find_by_name): Keep the list of
symbols sorted, return the slot where a new symbol must be inserted on
lookup failures.
(oblist_add_by_name): Add the new symbol at the given slot.
(mk_symbol): Adjust callsite.
(gensym): Likewise.
(assign_syntax): Likewise.
--
Optimize symbol lookups by keeping the lists in the hash table (or the
list if compiled with USE_OBJECT_LIST) sorted by the symbol names.
Optimize the insertions by passing the slot computed by the lookup to
the insertion.
Signed-off-by: Justus Winter <justus@g10code.com>
* tests/gpgscm/scheme-private.h (struct cell): Add a compact vector
representation.
* tests/gpgscm/scheme.c (vector_length): Use new representation.
(vector_size): New macro.
(get_vector_object): Use the new representation.
(fill_vector): Likewise.
(vector_elem): Likewise.
(set_vector_elem): Likewise.
(mark): Likewise.
(gc): Likewise. Be careful not to confuse immediate values for type
flags.
(finalize_cell): Vectors now require finalization.
--
Previously, vectors were represented using consecutive cons cells,
wasting one word per cell for the type information. Fix that by using
a flat array.
Previously, a vector of size N required 1 + (n + 1) / 2 cells. Now it
uses 1 + (n - 1 + 2) / 3 cells.
Signed-off-by: Justus Winter <justus@g10code.com>
* tests/gpgscm/scheme.c (IMMEDIATE_TAG): New macro.
({is,set,clr}_immediate): Likewise.
(enum scheme_types): Make type tags disjoint from immediate values.
(TYPE_BITS): We need one more bit now.
(ADJ,T_MASKTYPE): Compute values.
--
Immediate values are disjoint from all type tags and pointers,
allowing us to store immediate values in all memory locations.
Signed-off-by: Justus Winter <justus@g10code.com>