Compare commits

...

3 Commits

Author SHA1 Message Date
ca544088d6 Performance upgrade.
All checks were successful
CI / Optimization Infrastructure Tests (push) Successful in 14s
CI / Unit Tests (push) Successful in 43s
CI / Integration Tests (push) Successful in 21s
CI / Performance Benchmark (push) Successful in 1m29s
2025-12-08 07:15:25 +01:00
7b69ff62f6 WOrking benchmark. 2025-12-08 03:13:33 +01:00
668e6b8b34 Huge performance upgrade. 2025-12-08 02:48:35 +01:00
7 changed files with 99 additions and 36 deletions

View File

@ -231,6 +231,7 @@ typedef union {
struct {
char *class_name;
char *field_name;
void *cached_ptr;
} field;
struct {
int local_index;
@ -266,8 +267,8 @@ typedef union {
typedef struct {
RavaOpCode_e opcode;
RavaOperand_u operand;
int line;
RavaOperand_u operand;
} RavaInstruction_t;
typedef struct {

View File

@ -270,6 +270,7 @@ static void _rava_ir_gen_expression(RavaIRGenerator_t *gen, RavaASTNode_t *expr)
instr.opcode = RAVA_OP_STORE_STATIC;
instr.operand.field.class_name = strdup(obj_name);
instr.operand.field.field_name = strdup(target_member->data.member_access.member);
instr.operand.field.cached_ptr = NULL;
_rava_ir_emit(gen, instr);
break;
}
@ -301,6 +302,7 @@ static void _rava_ir_gen_expression(RavaIRGenerator_t *gen, RavaASTNode_t *expr)
instr.opcode = RAVA_OP_LOAD_STATIC;
instr.operand.field.class_name = strdup(obj_name);
instr.operand.field.field_name = strdup(expr->data.member_access.member);
instr.operand.field.cached_ptr = NULL;
_rava_ir_emit(gen, instr);
break;
}

View File

@ -17,12 +17,12 @@
typedef struct {
RavaMethod_t* method;
RavaNanboxValue_t locals[RAVA_MAX_LOCALS_FIXED];
RavaNanboxValue_t stack[RAVA_MAX_STACK_FIXED];
size_t stack_top;
size_t pc;
size_t stack_top;
bool has_this;
RavaNanboxValue_t this_ref;
RavaNanboxValue_t locals[RAVA_MAX_LOCALS_FIXED];
RavaNanboxValue_t stack[RAVA_MAX_STACK_FIXED];
} FastFrame_t;
typedef struct {

View File

@ -157,4 +157,23 @@ static inline bool rava_nanbox_to_bool(RavaNanboxValue_t v) {
return true;
}
#define RAVA_NANBOX_BOTH_INT(a, b) (((a | b) & RAVA_TAG_MASK) == RAVA_TAG_LONG)
#define RAVA_NANBOX_BOTH_LONG(a, b) (((a | b) & RAVA_TAG_MASK) == RAVA_TAG_LONG)
static inline int64_t rava_nanbox_as_int_unchecked(RavaNanboxValue_t v) {
int64_t payload = (int64_t)(v & RAVA_PAYLOAD_MASK);
if (payload & 0x800000000000ULL) {
payload |= (int64_t)0xFFFF000000000000ULL;
}
return payload;
}
static inline int64_t rava_nanbox_as_long_unchecked(RavaNanboxValue_t v) {
int64_t payload = (int64_t)(v & RAVA_PAYLOAD_MASK);
if (payload & 0x800000000000ULL) {
payload |= (int64_t)0xFFFF000000000000ULL;
}
return payload;
}
#endif

View File

@ -145,10 +145,14 @@ static bool _rava_vm_execute_instruction(RavaVM_t *vm, RavaCallFrame_t *frame, R
snprintf(buf_b, sizeof(buf_b), "%ld", (long)rava_value_as_int(b));
str_b = buf_b;
}
size_t len = strlen(str_a) + strlen(str_b) + 1;
size_t len_a = strlen(str_a);
size_t len_b = strlen(str_b);
size_t len = len_a + len_b + 1;
char *result = malloc(len);
strcpy(result, str_a);
strcat(result, str_b);
if (result) {
memcpy(result, str_a, len_a);
memcpy(result + len_a, str_b, len_b + 1);
}
rava_stack_push(stack, rava_value_string(result));
free(result);
} else if (a.type == RAVA_VAL_LONG || b.type == RAVA_VAL_LONG) {
@ -2026,8 +2030,14 @@ op_load_field: {
}
op_load_static: {
RavaValue_t *field_val = rava_static_field_table_get(vm->static_fields,
instr->operand.field.class_name, instr->operand.field.field_name);
RavaValue_t *field_val = (RavaValue_t*)instr->operand.field.cached_ptr;
if (!field_val) {
field_val = rava_static_field_table_get(vm->static_fields,
instr->operand.field.class_name, instr->operand.field.field_name);
instr->operand.field.cached_ptr = field_val;
}
STACK_PUSH(stack, field_val ? *field_val : rava_value_int(0));
DISPATCH();
}
@ -2100,8 +2110,19 @@ op_store_field: {
op_store_static: {
RavaValue_t value = STACK_POP(stack);
rava_static_field_table_set(vm->static_fields, instr->operand.field.class_name,
instr->operand.field.field_name, value);
RavaValue_t *field_val = (RavaValue_t*)instr->operand.field.cached_ptr;
if (!field_val) {
rava_static_field_table_set(vm->static_fields, instr->operand.field.class_name,
instr->operand.field.field_name, value);
field_val = rava_static_field_table_get(vm->static_fields,
instr->operand.field.class_name, instr->operand.field.field_name);
if (field_val) {
instr->operand.field.cached_ptr = field_val;
}
} else {
*field_val = value;
}
DISPATCH();
}
@ -3395,8 +3416,8 @@ uf_store_local:
uf_add: {
RavaNanboxValue_t b = UF_POP();
RavaNanboxValue_t a = UF_POP();
if (LIKELY(rava_nanbox_is_int(a) && rava_nanbox_is_int(b))) {
UF_PUSH(rava_nanbox_int(rava_nanbox_as_int(a) + rava_nanbox_as_int(b)));
if (LIKELY(RAVA_NANBOX_BOTH_INT(a, b))) {
UF_PUSH(rava_nanbox_int(rava_nanbox_as_int_unchecked(a) + rava_nanbox_as_int_unchecked(b)));
} else if (UNLIKELY(rava_nanbox_is_string(a) || rava_nanbox_is_string(b))) {
char buf_a[64], buf_b[64];
const char *str_a, *str_b;
@ -3434,8 +3455,8 @@ uf_add: {
uf_sub: {
RavaNanboxValue_t b = UF_POP();
RavaNanboxValue_t a = UF_POP();
if (LIKELY(rava_nanbox_is_int(a) && rava_nanbox_is_int(b))) {
UF_PUSH(rava_nanbox_int(rava_nanbox_as_int(a) - rava_nanbox_as_int(b)));
if (LIKELY(RAVA_NANBOX_BOTH_INT(a, b))) {
UF_PUSH(rava_nanbox_int(rava_nanbox_as_int_unchecked(a) - rava_nanbox_as_int_unchecked(b)));
} else if (UNLIKELY(rava_nanbox_is_long(a) || rava_nanbox_is_long(b))) {
UF_PUSH(rava_nanbox_long(rava_nanbox_to_long(a) - rava_nanbox_to_long(b)));
} else {
@ -3447,8 +3468,8 @@ uf_sub: {
uf_mul: {
RavaNanboxValue_t b = UF_POP();
RavaNanboxValue_t a = UF_POP();
if (LIKELY(rava_nanbox_is_int(a) && rava_nanbox_is_int(b))) {
UF_PUSH(rava_nanbox_int(rava_nanbox_as_int(a) * rava_nanbox_as_int(b)));
if (LIKELY(RAVA_NANBOX_BOTH_INT(a, b))) {
UF_PUSH(rava_nanbox_int(rava_nanbox_as_int_unchecked(a) * rava_nanbox_as_int_unchecked(b)));
} else if (UNLIKELY(rava_nanbox_is_long(a) || rava_nanbox_is_long(b))) {
UF_PUSH(rava_nanbox_long(rava_nanbox_to_long(a) * rava_nanbox_to_long(b)));
} else {
@ -3462,8 +3483,8 @@ uf_div: {
RavaNanboxValue_t a = UF_POP();
int64_t bv = rava_nanbox_to_long(b);
if (UNLIKELY(bv == 0)) { UF_PUSH(rava_nanbox_int(0)); UF_DISPATCH(); }
if (LIKELY(rava_nanbox_is_int(a) && rava_nanbox_is_int(b))) {
UF_PUSH(rava_nanbox_int(rava_nanbox_as_int(a) / rava_nanbox_as_int(b)));
if (LIKELY(RAVA_NANBOX_BOTH_INT(a, b))) {
UF_PUSH(rava_nanbox_int(rava_nanbox_as_int_unchecked(a) / bv));
} else {
UF_PUSH(rava_nanbox_long(rava_nanbox_to_long(a) / bv));
}
@ -3475,8 +3496,8 @@ uf_mod: {
RavaNanboxValue_t a = UF_POP();
int64_t bv = rava_nanbox_to_long(b);
if (bv == 0) { UF_PUSH(rava_nanbox_int(0)); UF_DISPATCH(); }
if (rava_nanbox_is_int(a) && rava_nanbox_is_int(b)) {
UF_PUSH(rava_nanbox_int(rava_nanbox_as_int(a) % rava_nanbox_as_int(b)));
if (RAVA_NANBOX_BOTH_INT(a, b)) {
UF_PUSH(rava_nanbox_int(rava_nanbox_as_int_unchecked(a) % bv));
} else {
UF_PUSH(rava_nanbox_long(rava_nanbox_to_long(a) % bv));
}
@ -3978,14 +3999,33 @@ uf_store_field: {
}
uf_load_static: {
RavaValue_t *v = rava_static_field_table_get(vm->static_fields, instr->operand.field.class_name, instr->operand.field.field_name);
RavaValue_t *v = (RavaValue_t*)instr->operand.field.cached_ptr;
if (!v) {
v = rava_static_field_table_get(vm->static_fields, instr->operand.field.class_name, instr->operand.field.field_name);
instr->operand.field.cached_ptr = v;
}
UF_PUSH(v ? rava_value_to_nanbox(*v) : rava_nanbox_null());
UF_DISPATCH();
}
uf_store_static: {
RavaNanboxValue_t val = UF_POP();
rava_static_field_table_set(vm->static_fields, instr->operand.field.class_name, instr->operand.field.field_name, rava_nanbox_to_value(val));
RavaValue_t *field_val = (RavaValue_t*)instr->operand.field.cached_ptr;
if (!field_val) {
RavaValue_t value = rava_nanbox_to_value(val);
rava_static_field_table_set(vm->static_fields, instr->operand.field.class_name,
instr->operand.field.field_name, value);
field_val = rava_static_field_table_get(vm->static_fields,
instr->operand.field.class_name, instr->operand.field.field_name);
if (field_val) {
instr->operand.field.cached_ptr = field_val;
}
} else {
*field_val = rava_nanbox_to_value(val);
}
UF_DISPATCH();
}
@ -4418,8 +4458,8 @@ uf_add_local_to_local: {
int src = instr->operand.add_locals.src_index;
RavaNanboxValue_t d = frame->locals[dest];
RavaNanboxValue_t s = frame->locals[src];
if (rava_nanbox_is_int(d) && rava_nanbox_is_int(s)) {
frame->locals[dest] = rava_nanbox_int(rava_nanbox_as_int(d) + rava_nanbox_as_int(s));
if (RAVA_NANBOX_BOTH_INT(d, s)) {
frame->locals[dest] = rava_nanbox_int(rava_nanbox_as_int_unchecked(d) + rava_nanbox_as_int_unchecked(s));
} else {
frame->locals[dest] = rava_nanbox_long(rava_nanbox_to_long(d) + rava_nanbox_to_long(s));
}

View File

@ -99,9 +99,9 @@ struct RavaArrayList_t {
#define RAVA_HASHMAP_BUCKET_SIZE 32
typedef struct {
bool occupied;
char *key;
RavaValue_t value;
bool occupied;
} RavaHashMapEntry_t;
struct RavaHashMap_t {

View File

@ -54,8 +54,9 @@ RavaValue_t rava_arraylist_remove(RavaArrayList_t *list, size_t index) {
return rava_value_null();
}
RavaValue_t removed = list->data[index];
for (size_t i = index; i < list->size - 1; i++) {
list->data[i] = list->data[i + 1];
if (index < list->size - 1) {
memmove(&list->data[index], &list->data[index + 1],
(list->size - index - 1) * sizeof(RavaValue_t));
}
list->size--;
return removed;
@ -124,14 +125,14 @@ void rava_hashmap_put(RavaHashMap_t *map, const char *key, RavaValue_t value) {
}
unsigned int hash = _rava_hash_string(key);
size_t index = hash % map->bucket_count;
size_t index = hash & (map->bucket_count - 1);
while (map->buckets[index].occupied) {
if (strcmp(map->buckets[index].key, key) == 0) {
map->buckets[index].value = value;
return;
}
index = (index + 1) % map->bucket_count;
index = (index + 1) & (map->bucket_count - 1);
}
map->buckets[index].key = strdup(key);
@ -142,14 +143,14 @@ void rava_hashmap_put(RavaHashMap_t *map, const char *key, RavaValue_t value) {
RavaValue_t rava_hashmap_get(RavaHashMap_t *map, const char *key) {
unsigned int hash = _rava_hash_string(key);
size_t index = hash % map->bucket_count;
size_t index = hash & (map->bucket_count - 1);
size_t start = index;
while (map->buckets[index].occupied) {
if (strcmp(map->buckets[index].key, key) == 0) {
return map->buckets[index].value;
}
index = (index + 1) % map->bucket_count;
index = (index + 1) & (map->bucket_count - 1);
if (index == start) break;
}
@ -158,7 +159,7 @@ RavaValue_t rava_hashmap_get(RavaHashMap_t *map, const char *key) {
RavaValue_t rava_hashmap_remove(RavaHashMap_t *map, const char *key) {
unsigned int hash = _rava_hash_string(key);
size_t index = hash % map->bucket_count;
size_t index = hash & (map->bucket_count - 1);
size_t start = index;
while (map->buckets[index].occupied) {
@ -170,7 +171,7 @@ RavaValue_t rava_hashmap_remove(RavaHashMap_t *map, const char *key) {
map->size--;
return removed;
}
index = (index + 1) % map->bucket_count;
index = (index + 1) & (map->bucket_count - 1);
if (index == start) break;
}
@ -183,14 +184,14 @@ size_t rava_hashmap_size(RavaHashMap_t *map) {
bool rava_hashmap_containskey(RavaHashMap_t *map, const char *key) {
unsigned int hash = _rava_hash_string(key);
size_t index = hash % map->bucket_count;
size_t index = hash & (map->bucket_count - 1);
size_t start = index;
while (map->buckets[index].occupied) {
if (strcmp(map->buckets[index].key, key) == 0) {
return true;
}
index = (index + 1) % map->bucket_count;
index = (index + 1) & (map->bucket_count - 1);
if (index == start) break;
}