diff --git a/ir/ir.c b/ir/ir.c index c177b95..1d7bf3b 100644 --- a/ir/ir.c +++ b/ir/ir.c @@ -112,6 +112,19 @@ void rava_program_add_class(RavaProgram_t *program, RavaClass_t *class) { program->classes[program->class_count++] = class; } +void rava_program_prebuild_label_tables(RavaProgram_t *program) { + if (!program) return; + for (size_t i = 0; i < program->class_count; i++) { + RavaClass_t *class = program->classes[i]; + for (size_t j = 0; j < class->method_count; j++) { + RavaMethod_t *method = class->methods[j]; + if (!method->label_table && method->instructions) { + method->label_table = rava_labeltable_create(method->instructions); + } + } + } +} + static const char* _rava_opcode_name(RavaOpCode_e opcode) { switch (opcode) { case RAVA_OP_NOP: return "NOP"; diff --git a/ir/ir.h b/ir/ir.h index b938017..6e3f7be 100644 --- a/ir/ir.h +++ b/ir/ir.h @@ -224,6 +224,7 @@ void rava_class_add_method(RavaClass_t *class, RavaMethod_t *method); RavaProgram_t* rava_program_create(); void rava_program_destroy(RavaProgram_t *program); void rava_program_add_class(RavaProgram_t *program, RavaClass_t *class); +void rava_program_prebuild_label_tables(RavaProgram_t *program); void rava_ir_print(RavaProgram_t *program); diff --git a/ir/ir_gen.c b/ir/ir_gen.c index 62c41e0..2dfa1a1 100644 --- a/ir/ir_gen.c +++ b/ir/ir_gen.c @@ -1407,5 +1407,7 @@ RavaProgram_t* rava_ir_generate(RavaIRGenerator_t *generator, RavaASTNode_t *roo } } + rava_program_prebuild_label_tables(generator->program); + return generator->program; } diff --git a/lexer/lexer_keywords.c b/lexer/lexer_keywords.c index a4a0d48..b39a754 100644 --- a/lexer/lexer_keywords.c +++ b/lexer/lexer_keywords.c @@ -65,9 +65,17 @@ static const RavaKeyword_t KEYWORDS[] = { static const size_t KEYWORDS_COUNT = sizeof(KEYWORDS) / sizeof(KEYWORDS[0]); RavaTokenType_e rava_lexer_lookup_keyword(const char *identifier) { - for (size_t i = 0; i < KEYWORDS_COUNT; i++) { - if (strcmp(identifier, KEYWORDS[i].keyword) == 0) { - return KEYWORDS[i].type; + size_t low = 0; + size_t high = KEYWORDS_COUNT; + while (low < high) { + size_t mid = low + (high - low) / 2; + int cmp = strcmp(identifier, KEYWORDS[mid].keyword); + if (cmp == 0) { + return KEYWORDS[mid].type; + } else if (cmp < 0) { + high = mid; + } else { + low = mid + 1; } } return RAVA_TOKEN_IDENTIFIER; diff --git a/runtime/methodcache.c b/runtime/methodcache.c index a6af2ef..42ec339 100644 --- a/runtime/methodcache.c +++ b/runtime/methodcache.c @@ -25,10 +25,14 @@ RavaMethod_t* rava_methodcache_lookup(MethodCache_t* cache, MethodCacheEntry_t* entry = &cache->entries[idx]; - if (entry->class_hash == class_hash && - entry->method_hash == method_hash && - entry->method != NULL) { - return entry->method; + for (int i = 0; i < RAVA_METHOD_CACHE_WAYS; i++) { + MethodCacheSlot_t* slot = &entry->slots[i]; + if (slot->class_hash == class_hash && + slot->method_hash == method_hash && + slot->method != NULL) { + entry->lru = (uint8_t)i; + return slot->method; + } } return NULL; @@ -45,9 +49,22 @@ void rava_methodcache_insert(MethodCache_t* cache, uint32_t idx = (class_hash ^ method_hash) & RAVA_METHOD_CACHE_MASK; MethodCacheEntry_t* entry = &cache->entries[idx]; - entry->class_hash = class_hash; - entry->method_hash = method_hash; - entry->method = method; + + for (int i = 0; i < RAVA_METHOD_CACHE_WAYS; i++) { + if (entry->slots[i].method == NULL) { + entry->slots[i].class_hash = class_hash; + entry->slots[i].method_hash = method_hash; + entry->slots[i].method = method; + entry->lru = (uint8_t)i; + return; + } + } + + int evict = (entry->lru + 1) % RAVA_METHOD_CACHE_WAYS; + entry->slots[evict].class_hash = class_hash; + entry->slots[evict].method_hash = method_hash; + entry->slots[evict].method = method; + entry->lru = (uint8_t)evict; } void rava_methodcache_clear(MethodCache_t* cache) { diff --git a/runtime/methodcache.h b/runtime/methodcache.h index 70bd9e1..67947e1 100644 --- a/runtime/methodcache.h +++ b/runtime/methodcache.h @@ -7,11 +7,17 @@ #define RAVA_METHOD_CACHE_SIZE 256 #define RAVA_METHOD_CACHE_MASK (RAVA_METHOD_CACHE_SIZE - 1) +#define RAVA_METHOD_CACHE_WAYS 2 typedef struct { uint32_t class_hash; uint32_t method_hash; RavaMethod_t* method; +} MethodCacheSlot_t; + +typedef struct { + MethodCacheSlot_t slots[RAVA_METHOD_CACHE_WAYS]; + uint8_t lru; } MethodCacheEntry_t; typedef struct MethodCache_s { diff --git a/runtime/runtime.c b/runtime/runtime.c index 715fcf2..35a1c4c 100644 --- a/runtime/runtime.c +++ b/runtime/runtime.c @@ -51,55 +51,6 @@ #define VALUE_AS_INT_FAST(v) ((v).data.int_val) #define VALUE_AS_LONG_FAST(v) ((v).data.long_val) -RavaValue_t rava_value_int(int32_t value) { - RavaValue_t val; - val.type = RAVA_VAL_INT; - val.data.int_val = value; - return val; -} - -RavaValue_t rava_value_long(int64_t value) { - RavaValue_t val; - val.type = RAVA_VAL_LONG; - val.data.long_val = value; - return val; -} - -RavaValue_t rava_value_float(float value) { - RavaValue_t val; - val.type = RAVA_VAL_FLOAT; - val.data.float_val = value; - return val; -} - -RavaValue_t rava_value_double(double value) { - RavaValue_t val; - val.type = RAVA_VAL_DOUBLE; - val.data.double_val = value; - return val; -} - -RavaValue_t rava_value_boolean(bool value) { - RavaValue_t val; - val.type = RAVA_VAL_BOOLEAN; - val.data.bool_val = value; - return val; -} - -RavaValue_t rava_value_null() { - RavaValue_t val; - val.type = RAVA_VAL_NULL; - val.data.object_val = NULL; - return val; -} - -RavaValue_t rava_value_array(RavaArray_t *array) { - RavaValue_t val; - val.type = RAVA_VAL_ARRAY; - val.data.array_val = array; - return val; -} - RavaValue_t rava_value_string(const char *str) { RavaValue_t val; val.type = RAVA_VAL_STRING; @@ -235,6 +186,14 @@ size_t rava_array_length(RavaArray_t *array) { return array->length; } +static inline uint32_t _rava_field_hash(const char *name) { + uint32_t hash = 5381; + while (*name) { + hash = ((hash << 5) + hash) ^ (uint32_t)*name++; + } + return hash & (RAVA_OBJECT_HASH_SIZE - 1); +} + RavaObject_t* rava_object_create(const char *class_name) { RavaObject_t *obj = calloc(1, sizeof(RavaObject_t)); if (!obj) return NULL; @@ -243,6 +202,9 @@ RavaObject_t* rava_object_create(const char *class_name) { obj->field_names = calloc(obj->field_capacity, sizeof(char*)); obj->field_values = calloc(obj->field_capacity, sizeof(RavaValue_t)); obj->field_count = 0; + for (int i = 0; i < RAVA_OBJECT_HASH_SIZE; i++) { + obj->field_hash[i] = -1; + } return obj; } @@ -259,9 +221,16 @@ void rava_object_destroy(RavaObject_t *obj) { void rava_object_set_field(RavaObject_t *obj, const char *name, RavaValue_t value) { if (!obj || !name) return; + uint32_t h = _rava_field_hash(name); + int idx = obj->field_hash[h]; + if (idx >= 0 && (size_t)idx < obj->field_count && strcmp(obj->field_names[idx], name) == 0) { + obj->field_values[idx] = value; + return; + } for (size_t i = 0; i < obj->field_count; i++) { if (strcmp(obj->field_names[i], name) == 0) { obj->field_values[i] = value; + obj->field_hash[h] = (int)i; return; } } @@ -272,25 +241,26 @@ void rava_object_set_field(RavaObject_t *obj, const char *name, RavaValue_t valu } obj->field_names[obj->field_count] = strdup(name); obj->field_values[obj->field_count] = value; + obj->field_hash[h] = (int)obj->field_count; obj->field_count++; } RavaValue_t rava_object_get_field(RavaObject_t *obj, const char *name) { if (!obj || !name) return rava_value_null(); + uint32_t h = _rava_field_hash(name); + int idx = obj->field_hash[h]; + if (idx >= 0 && (size_t)idx < obj->field_count && strcmp(obj->field_names[idx], name) == 0) { + return obj->field_values[idx]; + } for (size_t i = 0; i < obj->field_count; i++) { if (strcmp(obj->field_names[i], name) == 0) { + obj->field_hash[h] = (int)i; return obj->field_values[i]; } } return rava_value_null(); } -RavaValue_t rava_value_object(RavaObject_t *obj) { - RavaValue_t val; - val.type = RAVA_VAL_OBJECT; - val.data.object_val = obj; - return val; -} int32_t rava_value_as_int(RavaValue_t value) { switch (value.type) { @@ -407,12 +377,18 @@ void rava_call_stack_destroy(RavaCallStack_t *stack) { free(stack); } -void rava_call_stack_push(RavaCallStack_t *stack, RavaCallFrame_t *frame) { +#define RAVA_MAX_CALL_STACK_DEPTH 10000 + +bool rava_call_stack_push(RavaCallStack_t *stack, RavaCallFrame_t *frame) { + if (stack->count >= RAVA_MAX_CALL_STACK_DEPTH) { + return false; + } if (stack->count >= stack->capacity) { stack->capacity *= 2; stack->frames = realloc(stack->frames, sizeof(RavaCallFrame_t*) * stack->capacity); } stack->frames[stack->count++] = frame; + return true; } RavaCallFrame_t* rava_call_stack_pop(RavaCallStack_t *stack) { @@ -426,11 +402,26 @@ RavaCallFrame_t* rava_call_stack_current(RavaCallStack_t *stack) { return stack->frames[stack->count - 1]; } +static inline uint32_t _rava_static_hash(const char *class_name, const char *field_name) { + uint32_t hash = 5381; + while (*class_name) { + hash = ((hash << 5) + hash) ^ (uint32_t)*class_name++; + } + hash = ((hash << 5) + hash) ^ '.'; + while (*field_name) { + hash = ((hash << 5) + hash) ^ (uint32_t)*field_name++; + } + return hash & (RAVA_STATIC_HASH_SIZE - 1); +} + static RavaStaticFieldTable_t* rava_static_field_table_create() { RavaStaticFieldTable_t *table = malloc(sizeof(RavaStaticFieldTable_t)); table->capacity = 16; table->fields = calloc(table->capacity, sizeof(RavaStaticField_t)); table->count = 0; + for (int i = 0; i < RAVA_STATIC_HASH_SIZE; i++) { + table->hash_table[i] = -1; + } return table; } @@ -447,9 +438,17 @@ static void rava_static_field_table_destroy(RavaStaticFieldTable_t *table) { static RavaValue_t* rava_static_field_table_get(RavaStaticFieldTable_t *table, const char *class_name, const char *field_name) { + uint32_t h = _rava_static_hash(class_name, field_name); + int idx = table->hash_table[h]; + if (idx >= 0 && (size_t)idx < table->count && + strcmp(table->fields[idx].class_name, class_name) == 0 && + strcmp(table->fields[idx].field_name, field_name) == 0) { + return &table->fields[idx].value; + } for (size_t i = 0; i < table->count; i++) { if (strcmp(table->fields[i].class_name, class_name) == 0 && strcmp(table->fields[i].field_name, field_name) == 0) { + table->hash_table[h] = (int)i; return &table->fields[i].value; } } @@ -460,11 +459,22 @@ static void rava_static_field_table_set(RavaStaticFieldTable_t *table, const char *class_name, const char *field_name, RavaValue_t value) { - RavaValue_t *existing = rava_static_field_table_get(table, class_name, field_name); - if (existing) { - *existing = value; + uint32_t h = _rava_static_hash(class_name, field_name); + int idx = table->hash_table[h]; + if (idx >= 0 && (size_t)idx < table->count && + strcmp(table->fields[idx].class_name, class_name) == 0 && + strcmp(table->fields[idx].field_name, field_name) == 0) { + table->fields[idx].value = value; return; } + for (size_t i = 0; i < table->count; i++) { + if (strcmp(table->fields[i].class_name, class_name) == 0 && + strcmp(table->fields[i].field_name, field_name) == 0) { + table->fields[i].value = value; + table->hash_table[h] = (int)i; + return; + } + } if (table->count >= table->capacity) { table->capacity *= 2; @@ -474,28 +484,22 @@ static void rava_static_field_table_set(RavaStaticFieldTable_t *table, table->fields[table->count].class_name = strdup(class_name); table->fields[table->count].field_name = strdup(field_name); table->fields[table->count].value = value; + table->hash_table[h] = (int)table->count; table->count++; } static RavaExceptionStack_t* rava_exception_stack_create() { RavaExceptionStack_t *stack = calloc(1, sizeof(RavaExceptionStack_t)); - stack->capacity = 16; - stack->handlers = calloc(stack->capacity, sizeof(RavaExceptionHandler_t)); stack->count = 0; return stack; } static void rava_exception_stack_destroy(RavaExceptionStack_t *stack) { - if (!stack) return; - free(stack->handlers); free(stack); } static void rava_exception_stack_push(RavaExceptionStack_t *stack, RavaExceptionHandler_t handler) { - if (stack->count >= stack->capacity) { - stack->capacity *= 2; - stack->handlers = realloc(stack->handlers, stack->capacity * sizeof(RavaExceptionHandler_t)); - } + if (stack->count >= RAVA_MAX_EXCEPTION_DEPTH) return; stack->handlers[stack->count++] = handler; } @@ -505,6 +509,14 @@ static bool rava_exception_stack_pop(RavaExceptionStack_t *stack, RavaExceptionH return true; } +static inline uint32_t _rava_class_hash(const char *name) { + uint32_t hash = 5381; + while (*name) { + hash = ((hash << 5) + hash) ^ (uint32_t)*name++; + } + return hash & (RAVA_CLASS_HASH_SIZE - 1); +} + RavaVM_t* rava_vm_create(RavaProgram_t *program) { RavaVM_t *vm = calloc(1, sizeof(RavaVM_t)); vm->program = program; @@ -516,6 +528,15 @@ RavaVM_t* rava_vm_create(RavaProgram_t *program) { vm->has_exception = false; vm->exception_value = rava_value_null(); vm->exception_stack = rava_exception_stack_create(); + + for (size_t i = 0; i < RAVA_CLASS_HASH_SIZE; i++) { + vm->class_hash[i] = -1; + } + for (size_t i = 0; i < program->class_count; i++) { + uint32_t h = _rava_class_hash(program->classes[i]->name); + vm->class_hash[h] = (int)i; + } + return vm; } @@ -532,8 +553,16 @@ void rava_vm_destroy(RavaVM_t *vm) { } static RavaClass_t* _rava_vm_find_class(RavaVM_t *vm, const char *class_name) { + uint32_t h = _rava_class_hash(class_name); + int idx = vm->class_hash[h]; + if (idx >= 0 && (size_t)idx < vm->program->class_count && + strcmp(vm->program->classes[idx]->name, class_name) == 0) { + return vm->program->classes[idx]; + } + for (size_t i = 0; i < vm->program->class_count; i++) { if (strcmp(vm->program->classes[i]->name, class_name) == 0) { + vm->class_hash[h] = (int)i; return vm->program->classes[i]; } } @@ -722,9 +751,21 @@ static bool _rava_vm_execute_instruction(RavaVM_t *vm, RavaCallFrame_t *frame, R RavaValue_t b = rava_stack_pop(stack); RavaValue_t a = rava_stack_pop(stack); if (a.type == RAVA_VAL_LONG || b.type == RAVA_VAL_LONG) { - rava_stack_push(stack, rava_value_long(rava_value_as_long(a) % rava_value_as_long(b))); + int64_t divisor = rava_value_as_long(b); + if (divisor == 0) { + vm->had_error = true; + vm->error_message = strdup("Division by zero"); + return false; + } + rava_stack_push(stack, rava_value_long(rava_value_as_long(a) % divisor)); } else { - rava_stack_push(stack, rava_value_int(rava_value_as_int(a) % rava_value_as_int(b))); + int32_t divisor = rava_value_as_int(b); + if (divisor == 0) { + vm->had_error = true; + vm->error_message = strdup("Division by zero"); + return false; + } + rava_stack_push(stack, rava_value_int(rava_value_as_int(a) % divisor)); } break; } @@ -861,7 +902,12 @@ static bool _rava_vm_execute_instruction(RavaVM_t *vm, RavaCallFrame_t *frame, R new_frame->locals[i] = rava_stack_pop(stack); } - rava_call_stack_push(vm->call_stack, new_frame); + if (!rava_call_stack_push(vm->call_stack, new_frame)) { + vm->had_error = true; + vm->error_message = strdup("Stack overflow"); + rava_call_frame_destroy(new_frame); + return false; + } while (new_frame->pc < new_frame->method->instructions->count) { RavaInstruction_t *next_instr = &new_frame->method->instructions->instructions[new_frame->pc]; @@ -920,7 +966,12 @@ static bool _rava_vm_execute_instruction(RavaVM_t *vm, RavaCallFrame_t *frame, R new_frame->locals[i] = args[i]; } - rava_call_stack_push(vm->call_stack, new_frame); + if (!rava_call_stack_push(vm->call_stack, new_frame)) { + vm->had_error = true; + vm->error_message = strdup("Stack overflow"); + rava_call_frame_destroy(new_frame); + return false; + } while (new_frame->pc < new_frame->method->instructions->count) { RavaInstruction_t *next_instr = &new_frame->method->instructions->instructions[new_frame->pc]; @@ -973,7 +1024,12 @@ static bool _rava_vm_execute_instruction(RavaVM_t *vm, RavaCallFrame_t *frame, R new_frame->locals[i] = args[i]; } - rava_call_stack_push(vm->call_stack, new_frame); + if (!rava_call_stack_push(vm->call_stack, new_frame)) { + vm->had_error = true; + vm->error_message = strdup("Stack overflow"); + rava_call_frame_destroy(new_frame); + return false; + } while (new_frame->pc < new_frame->method->instructions->count) { RavaInstruction_t *next_instr = &new_frame->method->instructions->instructions[new_frame->pc]; @@ -1767,8 +1823,9 @@ op_load_array: { RavaValue_t idx = STACK_POP(stack); RavaValue_t arr = STACK_POP(stack); if (arr.type == RAVA_VAL_ARRAY && arr.data.array_val) { - size_t index = (size_t)rava_value_as_int(idx); - if (index < arr.data.array_val->length) { + int32_t i = rava_value_as_int(idx); + if (i >= 0 && (size_t)i < arr.data.array_val->length) { + size_t index = (size_t)i; switch (arr.data.array_val->element_type) { case RAVA_VAL_INT: STACK_PUSH_INT(stack, ((int32_t*)arr.data.array_val->data)[index]); @@ -1818,8 +1875,9 @@ op_store_array: { RavaValue_t idx = STACK_POP(stack); RavaValue_t arr = STACK_POP(stack); if (arr.type == RAVA_VAL_ARRAY && arr.data.array_val) { - size_t index = (size_t)rava_value_as_int(idx); - if (index < arr.data.array_val->length) { + int32_t i = rava_value_as_int(idx); + if (i >= 0 && (size_t)i < arr.data.array_val->length) { + size_t index = (size_t)i; switch (arr.data.array_val->element_type) { case RAVA_VAL_INT: ((int32_t*)arr.data.array_val->data)[index] = rava_value_as_int(value); diff --git a/runtime/runtime.h b/runtime/runtime.h index b048989..ba05bf5 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -29,12 +29,15 @@ typedef struct { typedef struct RavaObject_t RavaObject_t; typedef struct RavaValue_t RavaValue_t; +#define RAVA_OBJECT_HASH_SIZE 16 + struct RavaObject_t { char *class_name; char **field_names; RavaValue_t *field_values; size_t field_count; size_t field_capacity; + int field_hash[RAVA_OBJECT_HASH_SIZE]; }; struct RavaValue_t { @@ -74,6 +77,8 @@ typedef struct { size_t count; } RavaCallStack_t; +#define RAVA_STATIC_HASH_SIZE 64 + typedef struct { char *class_name; char *field_name; @@ -84,6 +89,7 @@ typedef struct { RavaStaticField_t *fields; size_t count; size_t capacity; + int hash_table[RAVA_STATIC_HASH_SIZE]; } RavaStaticFieldTable_t; struct MethodCache_s; @@ -96,12 +102,15 @@ typedef struct { size_t stack_depth; } RavaExceptionHandler_t; +#define RAVA_MAX_EXCEPTION_DEPTH 64 + typedef struct { - RavaExceptionHandler_t *handlers; + RavaExceptionHandler_t handlers[RAVA_MAX_EXCEPTION_DEPTH]; size_t count; - size_t capacity; } RavaExceptionStack_t; +#define RAVA_CLASS_HASH_SIZE 32 + typedef struct { RavaProgram_t *program; RavaCallStack_t *call_stack; @@ -112,15 +121,65 @@ typedef struct { bool has_exception; RavaValue_t exception_value; RavaExceptionStack_t *exception_stack; + int class_hash[RAVA_CLASS_HASH_SIZE]; } RavaVM_t; -RavaValue_t rava_value_int(int32_t value); -RavaValue_t rava_value_long(int64_t value); -RavaValue_t rava_value_float(float value); -RavaValue_t rava_value_double(double value); -RavaValue_t rava_value_boolean(bool value); -RavaValue_t rava_value_null(); -RavaValue_t rava_value_array(RavaArray_t *array); +static inline RavaValue_t rava_value_int(int32_t value) { + RavaValue_t val; + val.type = RAVA_VAL_INT; + val.data.int_val = value; + return val; +} + +static inline RavaValue_t rava_value_long(int64_t value) { + RavaValue_t val; + val.type = RAVA_VAL_LONG; + val.data.long_val = value; + return val; +} + +static inline RavaValue_t rava_value_float(float value) { + RavaValue_t val; + val.type = RAVA_VAL_FLOAT; + val.data.float_val = value; + return val; +} + +static inline RavaValue_t rava_value_double(double value) { + RavaValue_t val; + val.type = RAVA_VAL_DOUBLE; + val.data.double_val = value; + return val; +} + +static inline RavaValue_t rava_value_boolean(bool value) { + RavaValue_t val; + val.type = RAVA_VAL_BOOLEAN; + val.data.bool_val = value; + return val; +} + +static inline RavaValue_t rava_value_null(void) { + RavaValue_t val; + val.type = RAVA_VAL_NULL; + val.data.object_val = NULL; + return val; +} + +static inline RavaValue_t rava_value_array(RavaArray_t *array) { + RavaValue_t val; + val.type = RAVA_VAL_ARRAY; + val.data.array_val = array; + return val; +} + +static inline RavaValue_t rava_value_object(RavaObject_t *obj) { + RavaValue_t val; + val.type = RAVA_VAL_OBJECT; + val.data.object_val = obj; + return val; +} + RavaValue_t rava_value_string(const char *str); int32_t rava_value_as_int(RavaValue_t value); @@ -141,7 +200,6 @@ RavaObject_t* rava_object_create(const char *class_name); void rava_object_destroy(RavaObject_t *obj); void rava_object_set_field(RavaObject_t *obj, const char *name, RavaValue_t value); RavaValue_t rava_object_get_field(RavaObject_t *obj, const char *name); -RavaValue_t rava_value_object(RavaObject_t *obj); RavaStack_t* rava_stack_create(size_t capacity); void rava_stack_destroy(RavaStack_t *stack); @@ -155,7 +213,7 @@ void rava_call_frame_destroy(RavaCallFrame_t *frame); RavaCallStack_t* rava_call_stack_create(); void rava_call_stack_destroy(RavaCallStack_t *stack); -void rava_call_stack_push(RavaCallStack_t *stack, RavaCallFrame_t *frame); +bool rava_call_stack_push(RavaCallStack_t *stack, RavaCallFrame_t *frame); RavaCallFrame_t* rava_call_stack_pop(RavaCallStack_t *stack); RavaCallFrame_t* rava_call_stack_current(RavaCallStack_t *stack); diff --git a/semantic/symbol_table.c b/semantic/symbol_table.c index 0e26d9e..1df685f 100644 --- a/semantic/symbol_table.c +++ b/semantic/symbol_table.c @@ -3,6 +3,14 @@ #include #include +static inline uint32_t _rava_symbol_hash(const char *name) { + uint32_t hash = 5381; + while (*name) { + hash = ((hash << 5) + hash) ^ (uint32_t)*name++; + } + return hash & (RAVA_SYMBOL_HASH_SIZE - 1); +} + RavaSymbolTable_t* rava_symbol_table_create() { RavaSymbolTable_t *table = malloc(sizeof(RavaSymbolTable_t)); table->global_scope = rava_scope_create("global", NULL); @@ -96,6 +104,11 @@ bool rava_symbol_table_define(RavaSymbolTable_t *table, RavaSymbol_t *symbol) { symbol->next = table->current_scope->symbols; table->current_scope->symbols = symbol; + + uint32_t h = _rava_symbol_hash(symbol->name); + symbol->hash_next = table->current_scope->hash_table[h]; + table->current_scope->hash_table[h] = symbol; + return true; } @@ -115,12 +128,13 @@ RavaSymbol_t* rava_symbol_table_resolve(RavaSymbolTable_t *table, const char *na RavaSymbol_t* rava_symbol_table_resolve_in_scope(RavaScope_t *scope, const char *name) { if (!scope || !name) return NULL; - RavaSymbol_t *symbol = scope->symbols; + uint32_t h = _rava_symbol_hash(name); + RavaSymbol_t *symbol = scope->hash_table[h]; while (symbol) { if (strcmp(symbol->name, name) == 0) { return symbol; } - symbol = symbol->next; + symbol = symbol->hash_next; } return NULL; diff --git a/semantic/symbol_table.h b/semantic/symbol_table.h index ce6dfb5..e7e69da 100644 --- a/semantic/symbol_table.h +++ b/semantic/symbol_table.h @@ -6,6 +6,8 @@ #include #include +#define RAVA_SYMBOL_HASH_SIZE 16 + typedef enum { RAVA_SYMBOL_CLASS, RAVA_SYMBOL_METHOD, @@ -24,11 +26,13 @@ typedef struct RavaSymbol_t { size_t local_index; struct RavaSymbol_t *next; + struct RavaSymbol_t *hash_next; } RavaSymbol_t; typedef struct RavaScope_t { char *name; RavaSymbol_t *symbols; + RavaSymbol_t *hash_table[RAVA_SYMBOL_HASH_SIZE]; struct RavaScope_t *parent; struct RavaScope_t **children; size_t children_count; diff --git a/types/types.c b/types/types.c index 6477f4a..d953c23 100644 --- a/types/types.c +++ b/types/types.c @@ -4,24 +4,44 @@ #include #include +static RavaType_t _type_void = { RAVA_TYPE_VOID, "void", { .array = { NULL, 0 } } }; +static RavaType_t _type_boolean = { RAVA_TYPE_BOOLEAN, "boolean", { .array = { NULL, 0 } } }; +static RavaType_t _type_byte = { RAVA_TYPE_BYTE, "byte", { .array = { NULL, 0 } } }; +static RavaType_t _type_short = { RAVA_TYPE_SHORT, "short", { .array = { NULL, 0 } } }; +static RavaType_t _type_int = { RAVA_TYPE_INT, "int", { .array = { NULL, 0 } } }; +static RavaType_t _type_long = { RAVA_TYPE_LONG, "long", { .array = { NULL, 0 } } }; +static RavaType_t _type_char = { RAVA_TYPE_CHAR, "char", { .array = { NULL, 0 } } }; +static RavaType_t _type_float = { RAVA_TYPE_FLOAT, "float", { .array = { NULL, 0 } } }; +static RavaType_t _type_double = { RAVA_TYPE_DOUBLE, "double", { .array = { NULL, 0 } } }; +static RavaType_t _type_null = { RAVA_TYPE_NULL, "null", { .array = { NULL, 0 } } }; +static RavaType_t _type_string = { RAVA_TYPE_CLASS, "String", { .class_type = { "String" } } }; + +static inline bool _is_pooled_type(RavaType_t *type) { + return type == &_type_void || type == &_type_boolean || type == &_type_byte || + type == &_type_short || type == &_type_int || type == &_type_long || + type == &_type_char || type == &_type_float || type == &_type_double || + type == &_type_null || type == &_type_string; +} + RavaType_t* rava_type_create_primitive(RavaTypeKind_e kind) { - RavaType_t *type = calloc(1, sizeof(RavaType_t)); - type->kind = kind; - switch (kind) { - case RAVA_TYPE_VOID: type->name = strdup("void"); break; - case RAVA_TYPE_BOOLEAN: type->name = strdup("boolean"); break; - case RAVA_TYPE_BYTE: type->name = strdup("byte"); break; - case RAVA_TYPE_SHORT: type->name = strdup("short"); break; - case RAVA_TYPE_INT: type->name = strdup("int"); break; - case RAVA_TYPE_LONG: type->name = strdup("long"); break; - case RAVA_TYPE_CHAR: type->name = strdup("char"); break; - case RAVA_TYPE_FLOAT: type->name = strdup("float"); break; - case RAVA_TYPE_DOUBLE: type->name = strdup("double"); break; - default: type->name = strdup("unknown"); break; + case RAVA_TYPE_VOID: return &_type_void; + case RAVA_TYPE_BOOLEAN: return &_type_boolean; + case RAVA_TYPE_BYTE: return &_type_byte; + case RAVA_TYPE_SHORT: return &_type_short; + case RAVA_TYPE_INT: return &_type_int; + case RAVA_TYPE_LONG: return &_type_long; + case RAVA_TYPE_CHAR: return &_type_char; + case RAVA_TYPE_FLOAT: return &_type_float; + case RAVA_TYPE_DOUBLE: return &_type_double; + case RAVA_TYPE_NULL: return &_type_null; + default: { + RavaType_t *type = calloc(1, sizeof(RavaType_t)); + type->kind = kind; + type->name = strdup("unknown"); + return type; + } } - - return type; } RavaType_t* rava_type_create_class(const char *class_name) { @@ -49,7 +69,7 @@ RavaType_t* rava_type_create_array(RavaType_t *element_type, int dimensions) { } void rava_type_destroy(RavaType_t *type) { - if (!type) return; + if (!type || _is_pooled_type(type)) return; free(type->name); @@ -156,7 +176,7 @@ RavaType_t* rava_type_binary_result(RavaType_t *left, RavaType_t *right) { if (!left || !right) return NULL; if (_is_string_type(left) || _is_string_type(right)) { - return rava_type_create_class("String"); + return &_type_string; } if (!rava_type_is_numeric(left) || !rava_type_is_numeric(right)) { @@ -164,18 +184,18 @@ RavaType_t* rava_type_binary_result(RavaType_t *left, RavaType_t *right) { } if (left->kind == RAVA_TYPE_DOUBLE || right->kind == RAVA_TYPE_DOUBLE) { - return rava_type_create_primitive(RAVA_TYPE_DOUBLE); + return &_type_double; } if (left->kind == RAVA_TYPE_FLOAT || right->kind == RAVA_TYPE_FLOAT) { - return rava_type_create_primitive(RAVA_TYPE_FLOAT); + return &_type_float; } if (left->kind == RAVA_TYPE_LONG || right->kind == RAVA_TYPE_LONG) { - return rava_type_create_primitive(RAVA_TYPE_LONG); + return &_type_long; } - return rava_type_create_primitive(RAVA_TYPE_INT); + return &_type_int; } RavaType_t* rava_type_unary_result(RavaType_t *operand) { @@ -188,7 +208,7 @@ RavaType_t* rava_type_unary_result(RavaType_t *operand) { if (operand->kind == RAVA_TYPE_BYTE || operand->kind == RAVA_TYPE_SHORT || operand->kind == RAVA_TYPE_CHAR) { - return rava_type_create_primitive(RAVA_TYPE_INT); + return &_type_int; } return rava_type_create_primitive(operand->kind);