summaryrefslogtreecommitdiffstats
path: root/tests/gpgscm/scheme-private.h (follow)
Commit message (Collapse)AuthorAgeFilesLines
* gpgscm: Create and re-use frame objects.Justus Winter2017-05-031-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * 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>
* gpgscm: Merge opexe_0.Justus Winter2017-05-031-1/+0
| | | | | | | | | | | | | | | | * 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>
* gpgscm: Avoid fruitless garbage collection cycles.Justus Winter2017-04-241-0/+7
| | | | | | | | | * 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>
* gpgscm: Remove now obsolete dispatcher function from the opcodes.Justus Winter2017-04-101-1/+1
| | | | | | | | | | | | * tests/gpgscm/opdefines.h: Remove now obsolete dispatcher function from the opcodes. * tests/gpgscm/scheme-private.h (_OP_DEF): Adapt. * tests/gpgscm/scheme.c (dispatch_func): Remove type declaration. (op_code_info): Remove 'func'. (_OP_DEF): Adapt. (Eval_Cycle): Always call 'opexe_0'. Signed-off-by: Justus Winter <justus@g10code.com>
* gpgscm: Allocate small integers in the rodata section.Justus Winter2017-04-071-6/+1
| | | | | | | | | | | | | | | | | | | | | | | | | * 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>
* gpgscm: Make global data constant when possible.Justus Winter2017-04-071-1/+1
| | | | | | | | | | | | | | | | | | * 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>
* gpgscm: Remove arbitrary limit on number of cell segments.Justus Winter2017-04-071-8/+2
| | | | | | | | | | | | | | | | | | | | | | | * 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>
* gpgscm: Fix compact vector encoding.Justus Winter2017-04-071-1/+2
| | | | | | | | | | | | | | | | * tests/gpgscm/scheme-private.h (struct cell): Use uintptr_t for '_flags'. This way, '_flags' has the size of a machine word. -- The compact vector representation introduced in 49e2ae65 requires that we can tell apart pointers and type flags. This did not work on 64-bit big-endian architectures. Fixes a crash on 64-bit big-endian architectures. Hat-tip-to: gniibe Fixes-commit: 49e2ae65e892f93be7f87cfaae3392b50a99e4b1 Signed-off-by: Justus Winter <justus@g10code.com>
* gpgscm: Track source locations in every kind of ports.Justus Winter2017-02-281-4/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * 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>
* gpgscm: Use a compact vector representation.Justus Winter2017-01-301-0/+4
| | | | | | | | | | | | | | | | | | | | | | | | | * 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>
* gpgscm: Use boxed values for source locations.Justus Winter2017-01-021-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | * tests/gpgscm/scheme-private.h (struct port): Use boxed values for filename and current line. This allows us to use the same Scheme object for labeling all expressions in a file. * tests/gpgscm/scheme.c (file_push): Use boxed type for filename. (mark): Mark location objects of port objects. (gc): Mark location objects in the load stack. (port_clear_location): New function. (port_reset_current_line): Likewise. (port_increment_current_line): Likewise. (file_pop): Adapt accordingly. (port_rep_from_filename): Likewise. (port_rep_from_file): Likewise. (port_close): Likewise. (skipspace): Likewise. (token): Likewise. (_Error_1): Likewise. (opexe_0): Likewise. (opexe_5): Likewise. (scheme_deinit): Likewise. (scheme_load_file): Likewise. (scheme_load_named_file): Likewise. Signed-off-by: Justus Winter <justus@g10code.com>
* gpgscm: Keep a history of calls for error messages.Justus Winter2016-12-081-0/+33
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * tests/gpgscm/init.scm (vm-history-print): New function. * tests/gpgscm/opdefines.h: New opcodes 'CALLSTACK_POP', 'APPLY_CODE', and 'VM_HISTORY'. * tests/gpgscm/scheme-private.h (struct history): New definition. (struct scheme): New field 'history'. * tests/gpgscm/scheme.c (gc): Mark objects in the history. (history_free): New function. (history_init): Likewise. (history_mark): Likewise. (add_mod): New macro. (sub_mod): Likewise. (tailstack_clear): New function. (callstack_pop): Likewise. (callstack_push): Likewise. (tailstack_push): Likewise. (tailstack_flatten): Likewise. (callstack_flatten): Likewise. (history_flatten): Likewise. (opexe_0): New variable 'callsite', keep track of the expression if it is a call, implement the new opcodes, record function applications in the history. (opexe_6): Implement new opcode. (scheme_init_custom_alloc): Initialize history. (scheme_deinit): Free history. * tests/gpgscm/scheme.h (USE_HISTORY): New macro. -- This patch makes TinySCHEME keep a history of function calls. This history can be used to produce helpful error messages. The history data structure is inspired by MIT/GNU Scheme. Signed-off-by: Justus Winter <justus@g10code.com> fu history
* gpgscm: Add flags to the interpreter.Justus Winter2016-12-081-0/+1
| | | | | | | | | | | | * tests/gpgscm/scheme-private.h (struct scheme): Add field 'flags'. * tests/gpgscm/scheme.c (S_OP_MASK): New macro. (S_FLAG_MASK, s_set_flag, s_clear_flag, s_get_flag): Likewise. (_s_return): Unpack the encoded opcode and flags. (s_save): Encode the flags along with the opcode. Use normal integers to encode the result. (scheme_init_custom_alloc): Initialize 'op' and 'flags'. Signed-off-by: Justus Winter <justus@g10code.com>
* gpgscm: Use a static pool of cells for small integers.Justus Winter2016-11-221-0/+6
| | | | | | | | | | | | | | | | | | * tests/gpgscm/scheme-private.h (struct scheme): New fields for the static integer cells. * tests/gpgscm/scheme.c (_alloc_cellseg): New function. (alloc_cellseg): Use the new function. (MAX_SMALL_INTEGER): New macro. (initialize_small_integers): New function. (mk_small_integer): Likewise. (mk_integer): Return a small integer if possible. (_s_return): Do not free 'op' if it is a small integer. (s_save): Use a small integer to box the opcode. (scheme_init_custom_alloc): Initialize small integers. (scheme_deinit): Free chunk of small integers. * tests/gpgscm/scheme.h (USE_SMALL_INTEGERS): New macro. Signed-off-by: Justus Winter <justus@g10code.com>
* gpgscm: Avoid cell allocation overhead.Justus Winter2016-11-141-0/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * tests/gpgscm/scheme-private.h (struct scheme): New fields 'inhibit_gc', 'reserved_cells', and 'reserved_lineno'. * tests/gpgscm/scheme.c (GC_ENABLED): New macro. (USE_GC_LOCKING): Likewise. (gc_reservations): Likewise. (gc_reservation_failure): New function. (_gc_disable): Likewise. (gc_disable): New macro. (gc_enable): Likewise. (gc_enabled): Likewise. (gc_consume): Likewise. (get_cell_x): Consume reserved cell if garbage collection is disabled. (_get_cell): Assert that gc is enabled. (get_cell): Only record cell in the list of recently allocated cells if gc is enabled. (get_vector_object): Likewise. (gc): Assert that gc is enabled. (s_return): Add comment, adjust call to '_s_return'. (s_return_enable_gc): New macro. (_s_return): Add flag 'enable_gc' and re-enable gc if set. (oblist_add_by_name): Use the new facilities to protect the allocations. (new_frame_in_env): Likewise. (new_slot_spec_in_env): Likewise. (s_save): Likewise. (opexe_0): Likewise. (opexe_1): Likewise. (opexe_2): Likewise. (opexe_5): Likewise. (opexe_6): Likewise. (scheme_init_custom_alloc): Initialize the new fields. -- Every time a cell is allocated, the interpreter may run out of free cells and do a garbage collection. This is problematic because it might garbage collect objects that have been allocated, but are not yet made available to the interpreter. Previously, we would plug such newly allocated cells into the list of newly allocated objects rooted at car(sc->sink), but that requires allocating yet another cell increasing pressure on the memory management system. A faster alternative is to preallocate the cells needed for an operation and make sure the garbage collection is not run until all allocated objects are plugged in. This can be done with gc_disable and gc_enable. This optimization can be applied incrementally. This commit picks all low-hanging fruits. Signed-off-by: Justus Winter <justus@g10code.com>
* gpgscm: Make the compile-hook configurable.Justus Winter2016-11-101-0/+2
| | | | | | | | | | * tests/gpgscm/scheme-private.h (struct scheme): Make field 'COMPILE_HOOK' optional. * tests/gpgscm/scheme.c (opexe_0): Fix guard. (scheme_init_custom_alloc): Conditionally initialize 'COMPILE_HOOK'. * tests/gpgscm/scheme.h (USE_COMPILE_HOOK): Define to 1 by default. Signed-off-by: Justus Winter <justus@g10code.com>
* gpgscm: Remove dubious stack implementation.Justus Winter2016-11-101-2/+0
| | | | | | | | * tests/gpgscm/scheme-private.h (struct scheme): Remove related fields. * tests/gpgscm/scheme.c: Drop all !USE_SCHEME_STACK code. * tests/gpgscm/scheme.h (USE_SCHEME_STACK): Remove macro. Signed-off-by: Justus Winter <justus@g10code.com>
* tests/gpgscm: Fix use of pointer.NIIBE Yutaka2016-09-151-1/+1
| | | | | | | | | | | | | | | | | * tests/gpgscm/scheme-private.h (struct scheme): Use (void *) for alloc_seg. * tests/gpgscm/scheme.c (alloc_cellseg): Use (void *) for cp. Use (void *) for coercion of address calculation. -- In old C language, (char *) means an address. In modern C, it's specifically an address with alignment=1. It's good to use (void *) for an address, because newer compiler emits warnings. Note: in this particular case, it is just a warning and the code is safe against invalid alignment, though. Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
* tests/gpgscm: Foreign objects support for TinySCHEME.Justus Winter2016-06-171-0/+8
| | | | | | | | | | | | | | | | | | | | | * tests/gpgscm/scheme-private.h (struct cell): Add 'foreign_object'. (is_foreign_object): New prototype. (get_foreign_object_{vtable,data}): Likewise. * tests/gpgscm/scheme.c (enum scheme_types): New type. (is_foreign_object): New function. (get_foreign_object_{vtable,data}): Likewise. (mk_foreign_object): Likewise. (finalize_cell): Free foreign objects. (atom2str): Pretty-print foreign objects. (vtbl): Add new functions. * tests/gpgscm/scheme.h (struct foreign_object_vtable): New type. (mk_foreign_object): New prototype. (struct scheme_interface): Add new functions. Patch from Thomas Munro, https://sourceforge.net/p/tinyscheme/patches/13/ Signed-off-by: Justus Winter <justus@g10code.com>
* tests/gpgscm: Dynamically allocate string buffer.Justus Winter2016-06-171-2/+2
| | | | | | | | | | | | | | * tests/gpgscm/scheme-config.h (strbuff{,_size}): Make buffer dynamic. * tests/gpgscm/scheme.c (expand_strbuff): New function. (putcharacter): Adapt length test. (readstrexp): Expand buffer if necessary. (scheme_init_custom_alloc): Initialize buffer. (scheme_deinit): Free buffer. Patch from Thomas Munro, https://sourceforge.net/p/tinyscheme/patches/11/ Signed-off-by: Justus Winter <justus@g10code.com>
* tests/gpgscm: Verbatim import of latest TinySCHEME.Justus Winter2016-06-171-0/+220
Revision 110 from svn://svn.code.sf.net/p/tinyscheme/code/trunk * tests/gpgscm/COPYING: New file. * tests/gpgscm/Manual.txt: Likewise. * tests/gpgscm/init.scm: Likewise. * tests/gpgscm/opdefines.h: Likewise. * tests/gpgscm/scheme-private.h: Likewise. * tests/gpgscm/scheme.c: Likewise. * tests/gpgscm/scheme.h: Likewise. Signed-off-by: Justus Winter <justus@g10code.com>