Commit dacb09b4 authored by Camil Staps's avatar Camil Staps 🍃

Move initialization of static nodes and computed goto labels to interpret.c (from parse.c)

parent b456c0b8
......@@ -85,6 +85,8 @@ deserialize_strict dsets graph thisexe w = case deserialize` True dsets graph th
deserialize` :: !Bool !DeserializationSettings !SerializedGraph !String !*World -> *(Maybe a, !*World)
deserialize` strict dsets {graph,descinfo,modules,bytecode} thisexe w
| not ensure_interpreter_init = abort "internal error in deserialize`\n"
# (host_syms,w) = accFiles (read_symbols thisexe) w
# pgm = parse host_syms bytecode
......@@ -163,6 +165,7 @@ where
get_start_rule_as_expression :: !DeserializationSettings !String !String !*World -> *(Maybe a, !*World)
get_start_rule_as_expression dsets filename prog w
| not ensure_interpreter_init = abort "internal error in get_start_rule_as_expression\n"
# (syms,w) = accFiles (read_symbols prog) w
# (bc,w) = readFile filename w
| isNothing bc = (Nothing, w)
......
......@@ -9,6 +9,7 @@ from _SystemArray import class Array
from StdMaybe import :: Maybe
from symbols_in_program import :: Symbol
ensure_interpreter_init :: Bool
parse :: !{#Symbol} !String -> Maybe Int
new_parser :: !{#Symbol} -> Int
new_string_char_provider :: !String -> Int
......
......@@ -27,6 +27,11 @@ import code from library "ucrtbase_library"
OFFSET_PARSER_PROGRAM :== IF_INT_64_OR_32 8 4 // Offset to the program field in the parser struct (parse.h)
ensure_interpreter_init :: Bool
ensure_interpreter_init = code {
ccall ensure_interpreter_init ":I"
}
parse :: !{#Symbol} !String -> Maybe Int
parse syms s
#! cp = new_string_char_provider s
......
......@@ -332,6 +332,48 @@ void install_interpreter_segv_handler(void) {
void *instruction_labels[CMAX]={NULL};
#endif
static int interpreter_initialized=0;
int ensure_interpreter_init(void) {
if (interpreter_initialized)
return 1;
prepare_static_nodes();
#ifdef LINK_CLEAN_RUNTIME
build_host_nodes();
#endif
#ifdef COMPUTED_GOTOS
/* Fetch label addresses */
if (instruction_labels[0]==NULL) {
interpret(NULL,
# ifdef LINK_CLEAN_RUNTIME
0,
# endif
NULL, 0, NULL, 0, NULL, NULL, NULL, NULL, NULL);
for (int i=0; i<32; i++)
Fjmp_ap[i]=(BC_WORD)instruction_labels[Fjmp_ap[i]];
__interpreter_cycle_in_spine[1]=(void*)instruction_labels[(BC_WORD)__interpreter_cycle_in_spine[1]];
__interpreter_indirection[0]=(void*)instruction_labels[(BC_WORD)__interpreter_indirection[0]];
__interpreter_indirection[1]=(void*)instruction_labels[(BC_WORD)__interpreter_indirection[1]];
__interpreter_indirection[2]=(void*)instruction_labels[(BC_WORD)__interpreter_indirection[2]];
__interpreter_indirection[3]=(void*)instruction_labels[(BC_WORD)__interpreter_indirection[3]];
__interpreter_indirection[5]=(void*)instruction_labels[(BC_WORD)__interpreter_indirection[5]];
__interpreter_indirection[7]=(void*)instruction_labels[(BC_WORD)__interpreter_indirection[7]];
__interpreter_indirection[8]=(void*)instruction_labels[(BC_WORD)__interpreter_indirection[8]];
# ifdef LINK_CLEAN_RUNTIME
for (int i = 0; i < 32; i++)
HOST_NODES[i][1]=instruction_labels[Cjsr_eval_host_node+i];
# endif
}
#endif
interpreter_initialized=1;
return 1;
}
int interpret(
#ifdef LINK_CLEAN_RUNTIME
struct interpretation_environment *ie,
......@@ -344,9 +386,18 @@ int interpret(
BC_WORD *_asp, BC_WORD *_bsp, BC_WORD *_csp, BC_WORD *_hp,
BC_WORD *_pc) {
#ifdef COMPUTED_GOTOS
if (stack == NULL) { /* See rationale in interpret.h */
if (instruction_labels[0] != NULL)
return 0;
/* When compiled with COMPUTED_GOTOS defined and stack=NULL, this function does
* not interpret at all but instead copy an array with label addresses to the
* instruction_labels array defined above. If anybody other than John (who,
* we're sure, will immediately understand) ever reads this, here is the
* rationale: with computed gotos, we want to store pointers to the label
* addresses in interpret_instructions.h instead of the bytecode values of the
* instructions themselves. However, compilers won't allow you to get a label
* address from outside a function (which is kind of silly). So, we call
* interpret(.., NULL, ..) from the parser to get an array with all the
* addresses needed.
*/
if (stack == NULL) {
# define _COMPUTED_GOTO_LABELS
# include "abc_instructions.h"
memcpy(instruction_labels, _instruction_labels, sizeof(BC_WORD) * CMAX);
......@@ -563,6 +614,8 @@ int main(int argc, char **argv) {
}
}
ensure_interpreter_init();
struct char_provider cp;
new_file_char_provider(&cp, input);
int res = parse_program(&state, &cp);
......
......@@ -112,21 +112,6 @@ extern void *instruction_labels[CMAX];
* node:
* - Pointer to a node to evaluate to HNF;
* - NULL if we should just start running at code[0].
*
* HOWEVER, when compiled with COMPUTED_GOTOS defined and stack=NULL, do not
* interpret at all but instead copy an array with label addresses to the
* instruction_labels array defined above. If anybody other than John (who,
* we're sure, will immediately understand) ever reads this, here is the
* rationale: with computed gotos, we want to store pointers to the label
* addresses in interpret_instructions.h instead of the bytecode values of the
* instructions themselves. However, compilers won't allow you to get a label
* address from outside a function (which is kind of silly). So, we call
* interpret(.., NULL, ..) from the parser to get an array with all the
* addresses needed. Why not just with an extra NULLable argument? Well, this
* function is called from Clean, which doesn't have a preprocessor so that the
* function signature has to be the same, whether we compile with or without
* computed gotos. Also, this implementation is faster, which is important for
* efficient lazy interpretation.
*/
int interpret(
#ifdef LINK_CLEAN_RUNTIME
......
......@@ -193,40 +193,6 @@ int parse_program(struct parser *state, struct char_provider *cp) {
int32_t elem32;
int64_t elem64;
#ifdef INTERPRETER
prepare_static_nodes();
#endif
#ifdef LINK_CLEAN_RUNTIME
build_host_nodes();
#endif
#ifdef COMPUTED_GOTOS
/* See rationale in interpret.h */
if (instruction_labels[0]==NULL) {
interpret(NULL,
#ifdef LINK_CLEAN_RUNTIME
0,
#endif
NULL, 0, NULL, 0, NULL, NULL, NULL, NULL, NULL);
for (int i=0; i<32; i++)
Fjmp_ap[i]=(BC_WORD)instruction_labels[Fjmp_ap[i]];
__interpreter_cycle_in_spine[1] = (void*) instruction_labels[(BC_WORD)__interpreter_cycle_in_spine[1]];
__interpreter_indirection[0] = (void*) instruction_labels[(BC_WORD)__interpreter_indirection[0]];
__interpreter_indirection[1] = (void*) instruction_labels[(BC_WORD)__interpreter_indirection[1]];
__interpreter_indirection[2] = (void*) instruction_labels[(BC_WORD)__interpreter_indirection[2]];
__interpreter_indirection[3] = (void*) instruction_labels[(BC_WORD)__interpreter_indirection[3]];
__interpreter_indirection[5] = (void*) instruction_labels[(BC_WORD)__interpreter_indirection[5]];
__interpreter_indirection[7] = (void*) instruction_labels[(BC_WORD)__interpreter_indirection[7]];
__interpreter_indirection[8] = (void*) instruction_labels[(BC_WORD)__interpreter_indirection[8]];
# ifdef LINK_CLEAN_RUNTIME
for (int i = 0; i < 32; i++)
HOST_NODES[i][1] = instruction_labels[Cjsr_eval_host_node+i];
# endif
}
#endif
while (state->state != PS_end) {
switch (state->state) {
case PS_init:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment