Compare commits
3 Commits
d22e4b0611
...
ca544088d6
| Author | SHA1 | Date | |
|---|---|---|---|
| ca544088d6 | |||
| 7b69ff62f6 | |||
| 668e6b8b34 |
3
ir/ir.h
3
ir/ir.h
@ -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 {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user