keep loop using the same dispatch table, removing the need to recreate the dispatch table

This commit is contained in:
William Bell
2025-09-01 21:51:16 +01:00
parent 19268f3070
commit b9c0503d54
6 changed files with 41 additions and 38 deletions

View File

@@ -30,7 +30,7 @@ native: $(CFILES) $(LEXER_C) $(LEXER_H)
debug: $(CFILES) $(LEXER_C) $(LEXER_H) debug: $(CFILES) $(LEXER_C) $(LEXER_H)
mkdir -p bin mkdir -p bin
gcc -g -O0 -o $(BINARY) $(CFILES) $(CFLAGS) gcc -g -O3 -o $(BINARY) $(CFILES) $(CFLAGS)
full-debug: $(CFILES) $(LEXER_C) $(LEXER_H) full-debug: $(CFILES) $(LEXER_C) $(LEXER_H)
mkdir -p bin mkdir -p bin

View File

@@ -1,3 +1,4 @@
let i = 1000000 let i = 10000000
while (i) do while (i) do
term.log(i)
i=i-1 i=i-1

2
app.py
View File

@@ -1,4 +1,4 @@
i = 1000000 i = 10000000
while i: while i:
print(i) print(i)
i=i-1 i=i-1

BIN
perf.data Normal file

Binary file not shown.

BIN
perf.data.old Normal file

Binary file not shown.

View File

@@ -671,8 +671,7 @@ static inline void load_variable(Translated *translated, RuntimeState *state,
arena_get(&translated->constants, offset)); arena_get(&translated->constants, offset));
return; return;
} }
static inline void run_instructions(Translated *translated, RuntimeState *state,
static inline void run_instruction(Translated *translated, RuntimeState *state,
struct Stack **stack, ArErr *err) { struct Stack **stack, ArErr *err) {
static void *dispatch_table[] = { static void *dispatch_table[] = {
[OP_LOAD_STRING] = &&DO_LOAD_STRING, [OP_LOAD_STRING] = &&DO_LOAD_STRING,
@@ -696,35 +695,41 @@ static inline void run_instruction(Translated *translated, RuntimeState *state,
[OP_ADDITION] = &&DO_ADDITION, [OP_ADDITION] = &&DO_ADDITION,
[OP_SUBTRACTION] = &&DO_SUBTRACTION, [OP_SUBTRACTION] = &&DO_SUBTRACTION,
[OP_LOAD_ACCESS_FUNCTION] = &&DO_LOAD_ACCESS_FUNCTION}; [OP_LOAD_ACCESS_FUNCTION] = &&DO_LOAD_ACCESS_FUNCTION};
START:
if (unlikely(state->head >= translated->bytecode.size || err->exists))
return;
goto *dispatch_table[pop_byte(translated, state)]; goto *dispatch_table[pop_byte(translated, state)];
DO_LOAD_NULL: DO_LOAD_NULL:
state->registers[pop_byte(translated, state)] = ARGON_NULL; state->registers[pop_byte(translated, state)] = ARGON_NULL;
return; goto START;
DO_LOAD_STRING: DO_LOAD_STRING:
load_const(translated, state); load_const(translated, state);
return; goto START;
DO_LOAD_NUMBER: DO_LOAD_NUMBER:
load_number(translated, state); load_number(translated, state);
return; goto START;
DO_LOAD_FUNCTION: DO_LOAD_FUNCTION:
load_argon_function(translated, state, *stack); load_argon_function(translated, state, *stack);
return; goto START;
DO_IDENTIFIER: DO_IDENTIFIER:
return load_variable(translated, state, *stack, err); load_variable(translated, state, *stack, err);
goto START;
DO_DECLARE: DO_DECLARE:
return runtime_declaration(translated, state, *stack, err); runtime_declaration(translated, state, *stack, err);
goto START;
DO_ASSIGN: DO_ASSIGN:
return runtime_assignment(translated, state, *stack); runtime_assignment(translated, state, *stack);
goto START;
DO_BOOL: { DO_BOOL: {
uint8_t to_register = pop_byte(translated, state); uint8_t to_register = pop_byte(translated, state);
if (likely(state->registers[0]->type != TYPE_OBJECT)) { if (likely(state->registers[0]->type != TYPE_OBJECT)) {
state->registers[to_register] = state->registers[to_register] =
state->registers[0]->as_bool ? ARGON_TRUE : ARGON_FALSE; state->registers[0]->as_bool ? ARGON_TRUE : ARGON_FALSE;
return; goto START;
} }
ArgonObject *args[] = {ARGON_BOOL_TYPE, state->registers[0]}; ArgonObject *args[] = {ARGON_BOOL_TYPE, state->registers[0]};
state->registers[to_register] = ARGON_BOOL_TYPE___new__(2, args, err, state); state->registers[to_register] = ARGON_BOOL_TYPE___new__(2, args, err, state);
return; goto START;
} }
DO_JUMP_IF_FALSE: { DO_JUMP_IF_FALSE: {
uint8_t from_register = pop_byte(translated, state); uint8_t from_register = pop_byte(translated, state);
@@ -732,17 +737,17 @@ DO_JUMP_IF_FALSE: {
if (state->registers[from_register] == ARGON_FALSE) { if (state->registers[from_register] == ARGON_FALSE) {
state->head = to; state->head = to;
} }
return; goto START;
} }
DO_JUMP: DO_JUMP:
state->head = pop_bytecode(translated, state); state->head = pop_bytecode(translated, state);
return; goto START;
DO_NEW_SCOPE: DO_NEW_SCOPE:
*stack = create_scope(*stack); *stack = create_scope(*stack);
return; goto START;
DO_POP_SCOPE: DO_POP_SCOPE:
*stack = (*stack)->prev; *stack = (*stack)->prev;
return; goto START;
DO_INIT_CALL: { DO_INIT_CALL: {
size_t length = pop_bytecode(translated, state); size_t length = pop_bytecode(translated, state);
call_instance call_instance = {state->call_instance, state->registers[0], call_instance call_instance = {state->call_instance, state->registers[0],
@@ -750,34 +755,34 @@ DO_INIT_CALL: {
length}; length};
state->call_instance = ar_alloc(sizeof(call_instance)); state->call_instance = ar_alloc(sizeof(call_instance));
*state->call_instance = call_instance; *state->call_instance = call_instance;
return; goto START;
} }
DO_INSERT_ARG:; DO_INSERT_ARG:;
size_t index = pop_bytecode(translated, state); size_t index = pop_bytecode(translated, state);
state->call_instance->args[index] = state->registers[0]; state->call_instance->args[index] = state->registers[0];
return; goto START;
DO_CALL: { DO_CALL: {
run_call(state->call_instance->to_call, state->call_instance->args_length, run_call(state->call_instance->to_call, state->call_instance->args_length,
state->call_instance->args, state, false, err); state->call_instance->args, state, false, err);
state->call_instance = (*state->call_instance).previous; state->call_instance = (*state->call_instance).previous;
return; goto START;
} }
DO_SOURCE_LOCATION: DO_SOURCE_LOCATION:
state->source_location = (SourceLocation){pop_bytecode(translated, state), state->source_location = (SourceLocation){pop_bytecode(translated, state),
pop_bytecode(translated, state), pop_bytecode(translated, state),
pop_bytecode(translated, state)}; pop_bytecode(translated, state)};
return; goto START;
DO_LOAD_BOOL: DO_LOAD_BOOL:
state->registers[0] = pop_byte(translated, state) ? ARGON_TRUE : ARGON_FALSE; state->registers[0] = pop_byte(translated, state) ? ARGON_TRUE : ARGON_FALSE;
return; goto START;
DO_LOAD_ACCESS_FUNCTION: DO_LOAD_ACCESS_FUNCTION:
state->registers[0] = ACCESS_FUNCTION; state->registers[0] = ACCESS_FUNCTION;
return; goto START;
DO_COPY_TO_REGISTER: { DO_COPY_TO_REGISTER: {
uint8_t from_register = pop_byte(translated, state); uint8_t from_register = pop_byte(translated, state);
uint64_t to_register = pop_byte(translated, state); uint64_t to_register = pop_byte(translated, state);
state->registers[to_register] = state->registers[from_register]; state->registers[to_register] = state->registers[from_register];
return; goto START;
} }
DO_ADDITION: { DO_ADDITION: {
uint8_t registerA = pop_byte(translated, state); uint8_t registerA = pop_byte(translated, state);
@@ -797,7 +802,7 @@ DO_ADDITION: {
if (!gonna_overflow) { if (!gonna_overflow) {
state->registers[registerC] = state->registers[registerC] =
new_number_object_from_num_and_den(a + b, 1); new_number_object_from_num_and_den(a + b, 1);
return; goto START;
} }
mpq_t a_GMP, b_GMP; mpq_t a_GMP, b_GMP;
mpq_init(a_GMP); mpq_init(a_GMP);
@@ -832,12 +837,12 @@ DO_ADDITION: {
mpq_clear(a_GMP); mpq_clear(a_GMP);
mpq_clear(b_GMP); mpq_clear(b_GMP);
} }
return; goto START;
} }
ArgonObject *args[] = {valueA, valueB}; ArgonObject *args[] = {valueA, valueB};
state->registers[registerC] = ARGON_ADDITION_FUNCTION(2, args, err, state); state->registers[registerC] = ARGON_ADDITION_FUNCTION(2, args, err, state);
return; goto START;
} }
DO_SUBTRACTION: { DO_SUBTRACTION: {
uint8_t registerA = pop_byte(translated, state); uint8_t registerA = pop_byte(translated, state);
@@ -858,7 +863,7 @@ DO_SUBTRACTION: {
if (!gonna_overflow) { if (!gonna_overflow) {
state->registers[registerC] = state->registers[registerC] =
new_number_object_from_num_and_den(a - b, 1); new_number_object_from_num_and_den(a - b, 1);
return; goto START;
} }
mpq_t a_GMP, b_GMP; mpq_t a_GMP, b_GMP;
mpq_init(a_GMP); mpq_init(a_GMP);
@@ -893,13 +898,14 @@ DO_SUBTRACTION: {
mpq_clear(a_GMP); mpq_clear(a_GMP);
mpq_clear(b_GMP); mpq_clear(b_GMP);
} }
return; goto START;
} }
ArgonObject *args[] = {valueA, valueB}; ArgonObject *args[] = {valueA, valueB};
state->registers[registerC] = ARGON_ADDITION_FUNCTION(2, args, err, state); state->registers[registerC] = ARGON_ADDITION_FUNCTION(2, args, err, state);
return; goto START;
} }
goto START;
} }
RuntimeState init_runtime_state(Translated translated, char *path) { RuntimeState init_runtime_state(Translated translated, char *path) {
@@ -930,12 +936,8 @@ void runtime(Translated translated, RuntimeState state, Stack *stack,
*currentStackFrame = (StackFrame){translated, state, stack, NULL, 0}; *currentStackFrame = (StackFrame){translated, state, stack, NULL, 0};
currentStackFrame->state.currentStackFramePointer = &currentStackFrame; currentStackFrame->state.currentStackFramePointer = &currentStackFrame;
while (currentStackFrame) { while (currentStackFrame) {
while (likely(currentStackFrame->state.head < run_instructions(&currentStackFrame->translated, &currentStackFrame->state,
currentStackFrame->translated.bytecode.size &&
!err->exists)) {
run_instruction(&currentStackFrame->translated, &currentStackFrame->state,
&currentStackFrame->stack, err); &currentStackFrame->stack, err);
}
currentStackFrame = currentStackFrame->previousStackFrame; currentStackFrame = currentStackFrame->previousStackFrame;
} }
} }