feat: add power scaling factor to plot generation in plot.py

The plot.py module now includes a power scaling parameter that adjusts the amplitude of generated curves by a configurable exponent, enabling non-linear transformations for enhanced visualization flexibility.
This commit is contained in:
2025-12-04 05:14:22 +00:00
parent e768ed066c
commit ed69521892
18 changed files with 930 additions and 236 deletions
+9
View File
@@ -12,6 +12,9 @@
#define RAVA_MAX_LOCALS_FIXED 64
#define RAVA_MAX_STACK_FIXED 512
#define RAVA_INLINE_FRAME_LOCALS 8
#define RAVA_INLINE_FRAME_STACK 16
typedef struct {
RavaMethod_t* method;
RavaNanboxValue_t locals[RAVA_MAX_LOCALS_FIXED];
@@ -22,6 +25,12 @@ typedef struct {
RavaNanboxValue_t this_ref;
} FastFrame_t;
typedef struct {
RavaNanboxValue_t locals[RAVA_INLINE_FRAME_LOCALS];
RavaNanboxValue_t stack[RAVA_INLINE_FRAME_STACK];
int sp;
} RavaInlineFrame_t;
extern FastFrame_t rava_frame_pool[RAVA_MAX_CALL_DEPTH];
extern size_t rava_frame_depth;
+266 -200
View File
@@ -5,6 +5,7 @@
#include "nanbox.h"
#include "fastframe.h"
#include "superinst.h"
#include "../utils/safe_alloc.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
@@ -23,7 +24,8 @@
#define STACK_ENSURE_CAPACITY(stack) do { \
if ((stack)->top >= (stack)->capacity) { \
(stack)->capacity *= 2; \
(stack)->values = realloc((stack)->values, sizeof(RavaValue_t) * (stack)->capacity); \
RavaValue_t *_new_values = realloc((stack)->values, sizeof(RavaValue_t) * (stack)->capacity); \
if (_new_values) (stack)->values = _new_values; \
} \
} while(0)
@@ -133,7 +135,7 @@ static char* _rava_get_string_buffer(RavaVM_t *vm, size_t needed) {
static uint32_t _intern_hash(const char *str) {
uint32_t hash = 5381;
while (*str) hash = ((hash << 5) + hash) ^ (uint32_t)*str++;
return hash & (RAVA_INTERN_TABLE_SIZE - 1);
return hash;
}
static const char* _rava_intern_string(RavaVM_t *vm, const char *str) {
@@ -141,6 +143,14 @@ static const char* _rava_intern_string(RavaVM_t *vm, const char *str) {
for (size_t i = 0; i < RAVA_INTERN_TABLE_SIZE; i++) {
size_t idx = (h + i) & (RAVA_INTERN_TABLE_SIZE - 1);
if (vm->intern_table.strings[idx] == NULL) {
if (vm->intern_table.count >= RAVA_INTERN_TABLE_SIZE - 1) {
static bool warned = false;
if (!warned) {
fprintf(stderr, "Warning: String intern table full (%d entries)\n",
RAVA_INTERN_TABLE_SIZE);
warned = true;
}
}
vm->intern_table.strings[idx] = strdup(str);
vm->intern_table.count++;
return vm->intern_table.strings[idx];
@@ -152,156 +162,46 @@ static const char* _rava_intern_string(RavaVM_t *vm, const char *str) {
return strdup(str);
}
RavaArray_t* rava_array_create(RavaValueType_e element_type, size_t length) {
if (length > 1000000) {
length = 1000000;
}
RavaArray_t *array = malloc(sizeof(RavaArray_t));
if (!array) return NULL;
array->element_type = element_type;
array->length = length;
array->data = NULL;
switch (element_type) {
case RAVA_VAL_INT:
array->data = calloc(length, sizeof(int32_t));
break;
case RAVA_VAL_LONG:
array->data = calloc(length, sizeof(int64_t));
break;
case RAVA_VAL_DOUBLE:
array->data = calloc(length, sizeof(double));
break;
case RAVA_VAL_BOOLEAN:
array->data = calloc(length, sizeof(bool));
break;
case RAVA_VAL_ARRAY:
case RAVA_VAL_OBJECT:
array->data = calloc(length, sizeof(RavaValue_t));
break;
default:
array->data = calloc(length, sizeof(void*));
break;
}
if (!array->data && length > 0) {
free(array);
return NULL;
}
return array;
}
void rava_array_destroy(RavaArray_t *array) {
if (!array) return;
free(array->data);
free(array);
}
void rava_array_set_int(RavaArray_t *array, size_t index, int32_t value) {
if (!array || !array->data || index >= array->length) return;
((int32_t*)array->data)[index] = value;
}
int32_t rava_array_get_int(RavaArray_t *array, size_t index) {
if (!array || !array->data || index >= array->length) return 0;
return ((int32_t*)array->data)[index];
}
void rava_array_set_value(RavaArray_t *array, size_t index, RavaValue_t value) {
if (!array || !array->data || index >= array->length) return;
((RavaValue_t*)array->data)[index] = value;
}
RavaValue_t rava_array_get_value(RavaArray_t *array, size_t index) {
if (!array || !array->data || index >= array->length) return rava_value_null();
return ((RavaValue_t*)array->data)[index];
}
size_t rava_array_length(RavaArray_t *array) {
if (!array) return 0;
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;
obj->class_name = strdup(class_name);
obj->field_capacity = 8;
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;
}
void rava_object_destroy(RavaObject_t *obj) {
if (!obj) return;
free(obj->class_name);
for (size_t i = 0; i < obj->field_count; i++) {
free(obj->field_names[i]);
}
free(obj->field_names);
free(obj->field_values);
free(obj);
return hash;
}
static void _rava_object_set_field_vm(RavaObject_t *obj, const char *name, RavaValue_t value, RavaVM_t *vm) {
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;
uint32_t hash = _rava_field_hash(name);
for (size_t probe = 0; probe < RAVA_OBJECT_HASH_SIZE; probe++) {
uint32_t idx = (hash + probe) & (RAVA_OBJECT_HASH_SIZE - 1);
int field_idx = obj->field_hash[idx];
if (field_idx == -1) {
if (obj->field_count >= obj->field_capacity) {
size_t new_cap = obj->field_capacity * 2;
char **new_names = rava_safe_realloc(obj->field_names, new_cap * sizeof(char*));
RavaValue_t *new_values = rava_safe_realloc(obj->field_values, new_cap * sizeof(RavaValue_t));
if (!new_names || !new_values) return;
obj->field_names = new_names;
obj->field_values = new_values;
obj->field_capacity = new_cap;
}
obj->field_names[obj->field_count] = (char*)(vm ? _rava_intern_string(vm, name) : strdup(name));
obj->field_values[obj->field_count] = value;
obj->field_hash[idx] = (int)obj->field_count;
obj->field_count++;
return;
}
if ((size_t)field_idx < obj->field_count &&
strcmp(obj->field_names[field_idx], name) == 0) {
obj->field_values[field_idx] = value;
return;
}
}
if (obj->field_count >= obj->field_capacity) {
obj->field_capacity *= 2;
obj->field_names = realloc(obj->field_names, obj->field_capacity * sizeof(char*));
obj->field_values = realloc(obj->field_values, obj->field_capacity * sizeof(RavaValue_t));
}
obj->field_names[obj->field_count] = (char*)(vm ? _rava_intern_string(vm, name) : strdup(name));
obj->field_values[obj->field_count] = value;
obj->field_hash[h] = (int)obj->field_count;
obj->field_count++;
}
void rava_object_set_field(RavaObject_t *obj, const char *name, RavaValue_t value) {
_rava_object_set_field_vm(obj, name, value, NULL);
}
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();
}
@@ -346,8 +246,13 @@ bool rava_value_as_boolean(RavaValue_t value) {
RavaStack_t* rava_stack_create(size_t capacity) {
RavaStack_t *stack = malloc(sizeof(RavaStack_t));
if (!stack) return NULL;
stack->capacity = capacity;
stack->values = malloc(sizeof(RavaValue_t) * capacity);
if (!stack->values) {
free(stack);
return NULL;
}
stack->top = 0;
return stack;
}
@@ -361,7 +266,9 @@ void rava_stack_destroy(RavaStack_t *stack) {
void rava_stack_push(RavaStack_t *stack, RavaValue_t value) {
if (stack->top >= stack->capacity) {
stack->capacity *= 2;
stack->values = realloc(stack->values, sizeof(RavaValue_t) * stack->capacity);
RavaValue_t *new_values = rava_safe_realloc(stack->values, sizeof(RavaValue_t) * stack->capacity);
if (!new_values) return;
stack->values = new_values;
}
stack->values[stack->top++] = value;
}
@@ -386,12 +293,22 @@ bool rava_stack_is_empty(RavaStack_t *stack) {
RavaCallFrame_t* rava_call_frame_create(RavaMethod_t *method) {
RavaCallFrame_t *frame = calloc(1, sizeof(RavaCallFrame_t));
if (!frame) return NULL;
frame->method = method;
frame->local_count = method->local_count;
frame->locals = calloc(method->local_count, sizeof(RavaValue_t));
if (!frame->locals && method->local_count > 0) {
free(frame);
return NULL;
}
frame->pc = 0;
size_t stack_size = method->max_stack > 0 ? (size_t)method->max_stack : 64;
frame->operand_stack = rava_stack_create(stack_size);
if (!frame->operand_stack) {
free(frame->locals);
free(frame);
return NULL;
}
frame->has_this = false;
frame->this_ref = rava_value_null();
return frame;
@@ -406,8 +323,13 @@ void rava_call_frame_destroy(RavaCallFrame_t *frame) {
RavaCallStack_t* rava_call_stack_create() {
RavaCallStack_t *stack = malloc(sizeof(RavaCallStack_t));
if (!stack) return NULL;
stack->capacity = 256;
stack->frames = malloc(sizeof(RavaCallFrame_t*) * stack->capacity);
if (!stack->frames) {
free(stack);
return NULL;
}
stack->count = 0;
return stack;
}
@@ -429,7 +351,9 @@ bool rava_call_stack_push(RavaCallStack_t *stack, RavaCallFrame_t *frame) {
}
if (stack->count >= stack->capacity) {
stack->capacity *= 2;
stack->frames = realloc(stack->frames, sizeof(RavaCallFrame_t*) * stack->capacity);
RavaCallFrame_t **new_frames = rava_safe_realloc(stack->frames, sizeof(RavaCallFrame_t*) * stack->capacity);
if (!new_frames) return false;
stack->frames = new_frames;
}
stack->frames[stack->count++] = frame;
return true;
@@ -455,13 +379,18 @@ static inline uint32_t _rava_static_hash(const char *class_name, const char *fie
while (*field_name) {
hash = ((hash << 5) + hash) ^ (uint32_t)*field_name++;
}
return hash & (RAVA_STATIC_HASH_SIZE - 1);
return hash;
}
static RavaStaticFieldTable_t* rava_static_field_table_create() {
RavaStaticFieldTable_t *table = malloc(sizeof(RavaStaticFieldTable_t));
if (!table) return NULL;
table->capacity = 16;
table->fields = calloc(table->capacity, sizeof(RavaStaticField_t));
if (!table->fields) {
free(table);
return NULL;
}
table->count = 0;
for (int i = 0; i < RAVA_STATIC_HASH_SIZE; i++) {
table->hash_table[i] = -1;
@@ -482,18 +411,20 @@ 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;
uint32_t hash = _rava_static_hash(class_name, field_name);
for (size_t probe = 0; probe < RAVA_STATIC_HASH_SIZE; probe++) {
uint32_t slot = (hash + probe) & (RAVA_STATIC_HASH_SIZE - 1);
int idx = table->hash_table[slot];
if (idx == -1) {
return NULL;
}
if ((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;
}
}
return NULL;
@@ -503,37 +434,41 @@ static void rava_static_field_table_set(RavaStaticFieldTable_t *table,
const char *class_name,
const char *field_name,
RavaValue_t 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;
uint32_t hash = _rava_static_hash(class_name, field_name);
for (size_t probe = 0; probe < RAVA_STATIC_HASH_SIZE; probe++) {
uint32_t slot = (hash + probe) & (RAVA_STATIC_HASH_SIZE - 1);
int idx = table->hash_table[slot];
if (idx == -1) {
if (table->count >= table->capacity) {
size_t new_cap = table->capacity * 2;
RavaStaticField_t *new_fields = rava_safe_realloc(table->fields, sizeof(RavaStaticField_t) * new_cap);
if (!new_fields) return;
table->fields = new_fields;
table->capacity = new_cap;
}
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[slot] = (int)table->count;
table->count++;
return;
}
if ((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;
}
}
if (table->count >= table->capacity) {
table->capacity *= 2;
table->fields = realloc(table->fields, sizeof(RavaStaticField_t) * table->capacity);
}
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));
if (!stack) return NULL;
stack->count = 0;
return stack;
}
@@ -563,15 +498,20 @@ static inline uint32_t _rava_class_hash(const char *name) {
RavaVM_t* rava_vm_create(RavaProgram_t *program) {
RavaVM_t *vm = calloc(1, sizeof(RavaVM_t));
if (!vm) return NULL;
vm->program = program;
vm->call_stack = rava_call_stack_create();
vm->static_fields = rava_static_field_table_create();
vm->method_cache = rava_methodcache_create();
vm->exception_stack = rava_exception_stack_create();
if (!vm->call_stack || !vm->static_fields || !vm->method_cache || !vm->exception_stack) {
rava_vm_destroy(vm);
return NULL;
}
vm->error_message = NULL;
vm->had_error = false;
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;
@@ -949,8 +889,8 @@ static bool _rava_vm_execute_instruction(RavaVM_t *vm, RavaCallFrame_t *frame, R
instr->operand.call.method_name);
if (!method) {
vm->had_error = true;
vm->error_message = malloc(256);
snprintf(vm->error_message, 256, "Method not found: %s.%s",
vm->error_message = malloc(RAVA_ERROR_BUFFER_SIZE);
snprintf(vm->error_message, RAVA_ERROR_BUFFER_SIZE, "Method not found: %s.%s",
instr->operand.call.class_name,
instr->operand.call.method_name);
return false;
@@ -1012,8 +952,8 @@ static bool _rava_vm_execute_instruction(RavaVM_t *vm, RavaCallFrame_t *frame, R
break;
}
vm->had_error = true;
vm->error_message = malloc(256);
snprintf(vm->error_message, 256, "Method not found: %s.%s",
vm->error_message = malloc(RAVA_ERROR_BUFFER_SIZE);
snprintf(vm->error_message, RAVA_ERROR_BUFFER_SIZE, "Method not found: %s.%s",
class_name, instr->operand.call.method_name);
return false;
}
@@ -1070,8 +1010,8 @@ static bool _rava_vm_execute_instruction(RavaVM_t *vm, RavaCallFrame_t *frame, R
RavaMethod_t *method = _rava_vm_find_method_cached(vm, super_class, instr->operand.call.method_name);
if (!method) {
vm->had_error = true;
vm->error_message = malloc(256);
snprintf(vm->error_message, 256, "Super method not found: %s.%s",
vm->error_message = malloc(RAVA_ERROR_BUFFER_SIZE);
snprintf(vm->error_message, RAVA_ERROR_BUFFER_SIZE, "Super method not found: %s.%s",
super_class, instr->operand.call.method_name);
return false;
}
@@ -1778,13 +1718,13 @@ static bool _rava_vm_execute_fast(RavaVM_t *vm, RavaCallFrame_t *frame) {
static const void *dispatch_table[] = {
&&op_nop,
&&op_load_const, &&op_load_long, &&op_load_double, &&op_load_string,
&&op_load_local, &&op_load_field, &&op_load_static, &&op_load_array,
&&op_store_local, &&op_store_field, &&op_store_static, &&op_store_array,
&&op_load_local, &&op_load_field, &&op_load_static, &&op_load_array, &&op_load_array_unchecked,
&&op_store_local, &&op_store_field, &&op_store_static, &&op_store_array, &&op_store_array_unchecked,
&&op_add, &&op_sub, &&op_mul, &&op_div, &&op_mod, &&op_neg,
&&op_and, &&op_or, &&op_xor, &&op_not, &&op_bitnot, &&op_shl, &&op_shr, &&op_ushr,
&&op_eq, &&op_ne, &&op_lt, &&op_le, &&op_gt, &&op_ge,
&&op_jump, &&op_jump_if_true, &&op_jump_if_false, &&op_label,
&&op_call, &&op_call_static, &&op_call_recursive, &&op_call_virtual, &&op_call_super, &&op_call_native,
&&op_call, &&op_call_static, &&op_call_recursive, &&op_call_inline, &&op_call_virtual, &&op_call_super, &&op_call_native,
&&op_return, &&op_return_void,
&&op_new, &&op_new_array, &&op_new_array_of_arrays, &&op_array_length, &&op_get_field, &&op_put_field,
&&op_cast, &&op_instanceof,
@@ -1910,6 +1850,28 @@ op_load_array: {
DISPATCH();
}
op_load_array_unchecked: {
RavaValue_t idx = STACK_POP(stack);
RavaValue_t arr = STACK_POP(stack);
size_t index = (size_t)rava_value_as_int(idx);
switch (arr.data.array_val->element_type) {
case RAVA_VAL_INT:
STACK_PUSH_INT(stack, ((int32_t*)arr.data.array_val->data)[index]);
break;
case RAVA_VAL_LONG:
STACK_PUSH_LONG(stack, ((int64_t*)arr.data.array_val->data)[index]);
break;
case RAVA_VAL_ARRAY:
case RAVA_VAL_OBJECT:
STACK_PUSH(stack, ((RavaValue_t*)arr.data.array_val->data)[index]);
break;
default:
STACK_PUSH_INT(stack, ((int32_t*)arr.data.array_val->data)[index]);
break;
}
DISPATCH();
}
op_store_local:
frame->locals[instr->operand.var.index] = STACK_POP(stack);
DISPATCH();
@@ -1958,6 +1920,29 @@ op_store_array: {
DISPATCH();
}
op_store_array_unchecked: {
RavaValue_t value = STACK_POP(stack);
RavaValue_t idx = STACK_POP(stack);
RavaValue_t arr = STACK_POP(stack);
size_t index = (size_t)rava_value_as_int(idx);
switch (arr.data.array_val->element_type) {
case RAVA_VAL_INT:
((int32_t*)arr.data.array_val->data)[index] = rava_value_as_int(value);
break;
case RAVA_VAL_LONG:
((int64_t*)arr.data.array_val->data)[index] = rava_value_as_long(value);
break;
case RAVA_VAL_ARRAY:
case RAVA_VAL_OBJECT:
((RavaValue_t*)arr.data.array_val->data)[index] = value;
break;
default:
((int32_t*)arr.data.array_val->data)[index] = rava_value_as_int(value);
break;
}
DISPATCH();
}
op_add: {
RavaValue_t b = STACK_POP(stack);
RavaValue_t a = STACK_POP(stack);
@@ -2228,8 +2213,8 @@ op_call_static: {
instr->operand.call.class_name, instr->operand.call.method_name);
if (!target_method) {
vm->had_error = true;
vm->error_message = malloc(256);
snprintf(vm->error_message, 256, "Method not found: %s.%s",
vm->error_message = malloc(RAVA_ERROR_BUFFER_SIZE);
snprintf(vm->error_message, RAVA_ERROR_BUFFER_SIZE, "Method not found: %s.%s",
instr->operand.call.class_name, instr->operand.call.method_name);
goto done;
}
@@ -2272,6 +2257,28 @@ op_call_recursive: {
DISPATCH();
}
op_call_inline: {
frame->pc = pc;
RavaMethod_t *target_method = (RavaMethod_t*)instr->operand.call.cached_method;
if (UNLIKELY(!target_method)) {
goto done;
}
RavaCallFrame_t *new_frame = rava_call_frame_create(target_method);
for (int i = instr->operand.call.arg_count - 1; i >= 0; i--) {
new_frame->locals[i] = STACK_POP(stack);
}
rava_call_stack_push(vm->call_stack, new_frame);
if (!_rava_vm_execute_fast(vm, new_frame)) {
goto done;
}
if (!rava_stack_is_empty(new_frame->operand_stack)) {
STACK_PUSH(stack, rava_stack_pop(new_frame->operand_stack));
}
rava_call_stack_pop(vm->call_stack);
rava_call_frame_destroy(new_frame);
DISPATCH();
}
op_call_virtual: {
frame->pc = pc;
RavaValue_t this_val = stack->values[stack->top - instr->operand.call.arg_count - 1];
@@ -2286,8 +2293,8 @@ op_call_virtual: {
DISPATCH();
}
vm->had_error = true;
vm->error_message = malloc(256);
snprintf(vm->error_message, 256, "Method not found: %s.%s",
vm->error_message = malloc(RAVA_ERROR_BUFFER_SIZE);
snprintf(vm->error_message, RAVA_ERROR_BUFFER_SIZE, "Method not found: %s.%s",
target_class, instr->operand.call.method_name);
goto done;
}
@@ -2319,8 +2326,8 @@ op_call_super: {
RavaMethod_t *target_method = _rava_vm_find_method_cached(vm, super_class, instr->operand.call.method_name);
if (!target_method) {
vm->had_error = true;
vm->error_message = malloc(256);
snprintf(vm->error_message, 256, "Super method not found: %s.%s",
vm->error_message = malloc(RAVA_ERROR_BUFFER_SIZE);
snprintf(vm->error_message, RAVA_ERROR_BUFFER_SIZE, "Super method not found: %s.%s",
super_class, instr->operand.call.method_name);
goto done;
}
@@ -3056,13 +3063,13 @@ static bool _rava_vm_execute_ultrafast(RavaVM_t *vm, RavaMethod_t *entry_method)
static const void *dispatch_table[] = {
&&uf_nop,
&&uf_load_const, &&uf_load_long, &&uf_load_double, &&uf_load_string,
&&uf_load_local, &&uf_load_field, &&uf_load_static, &&uf_load_array,
&&uf_store_local, &&uf_store_field, &&uf_store_static, &&uf_store_array,
&&uf_load_local, &&uf_load_field, &&uf_load_static, &&uf_load_array, &&uf_load_array_unchecked,
&&uf_store_local, &&uf_store_field, &&uf_store_static, &&uf_store_array, &&uf_store_array_unchecked,
&&uf_add, &&uf_sub, &&uf_mul, &&uf_div, &&uf_mod, &&uf_neg,
&&uf_and, &&uf_or, &&uf_xor, &&uf_not, &&uf_bitnot, &&uf_shl, &&uf_shr, &&uf_ushr,
&&uf_eq, &&uf_ne, &&uf_lt, &&uf_le, &&uf_gt, &&uf_ge,
&&uf_jump, &&uf_jump_if_true, &&uf_jump_if_false, &&uf_label,
&&uf_call, &&uf_call_static, &&uf_call_recursive, &&uf_call_virtual, &&uf_call_super, &&uf_call_native,
&&uf_call, &&uf_call_static, &&uf_call_recursive, &&uf_call_inline, &&uf_call_virtual, &&uf_call_super, &&uf_call_native,
&&uf_return, &&uf_return_void,
&&uf_new, &&uf_new_array, &&uf_new_array_of_arrays, &&uf_array_length, &&uf_get_field, &&uf_put_field,
&&uf_cast, &&uf_instanceof,
@@ -3426,6 +3433,36 @@ uf_call_recursive: {
UF_DISPATCH();
}
uf_call_inline: {
RavaMethod_t *target = (RavaMethod_t*)instr->operand.call.cached_method;
if (UNLIKELY(!target)) {
vm->had_error = true;
goto uf_done;
}
if (!target->label_table) {
rava_optimize_superinstructions(target);
target->label_table = rava_labeltable_create(target->instructions);
}
RavaNanboxValue_t args[16];
for (int i = instr->operand.call.arg_count - 1; i >= 0; i--) {
args[i] = UF_POP();
}
frame->pc = pc;
FastFrame_t *new_frame = rava_fastframe_push(target, target->local_count);
if (!new_frame) {
vm->had_error = true;
goto uf_done;
}
for (int i = 0; i < instr->operand.call.arg_count; i++) {
new_frame->locals[i] = args[i];
}
frame = new_frame;
instructions = target->instructions->instructions;
instr_count = target->instructions->count;
pc = 0;
UF_DISPATCH();
}
uf_call_virtual: {
int arg_count = instr->operand.call.arg_count;
RavaNanboxValue_t args[16];
@@ -3583,6 +3620,21 @@ uf_load_array: {
UF_DISPATCH();
}
uf_load_array_unchecked: {
RavaNanboxValue_t idx = UF_POP();
RavaNanboxValue_t arr_val = UF_POP();
RavaArray_t *arr = rava_nanbox_as_array(arr_val);
size_t i = (size_t)rava_nanbox_to_int(idx);
if (arr->element_type == RAVA_VAL_ARRAY || arr->element_type == RAVA_VAL_OBJECT) {
RavaValue_t v = rava_array_get_value(arr, i);
UF_PUSH(rava_value_to_nanbox(v));
} else {
int32_t val = rava_array_get_int(arr, i);
UF_PUSH(rava_nanbox_int(val));
}
UF_DISPATCH();
}
uf_store_array: {
RavaNanboxValue_t val = UF_POP();
RavaNanboxValue_t idx = UF_POP();
@@ -3599,6 +3651,20 @@ uf_store_array: {
UF_DISPATCH();
}
uf_store_array_unchecked: {
RavaNanboxValue_t val = UF_POP();
RavaNanboxValue_t idx = UF_POP();
RavaNanboxValue_t arr_val = UF_POP();
RavaArray_t *arr = rava_nanbox_as_array(arr_val);
size_t i = (size_t)rava_nanbox_to_int(idx);
if (arr->element_type == RAVA_VAL_ARRAY || arr->element_type == RAVA_VAL_OBJECT) {
rava_array_set_value(arr, i, rava_nanbox_to_value(val));
} else {
rava_array_set_int(arr, i, rava_nanbox_to_int(val));
}
UF_DISPATCH();
}
uf_get_field:
uf_load_field: {
RavaNanboxValue_t obj_val = UF_POP();
@@ -4233,8 +4299,8 @@ bool rava_vm_execute(RavaVM_t *vm, const char *class_name, const char *method_na
RavaMethod_t *method = _rava_vm_find_method_cached(vm, class_name, method_name);
if (!method) {
vm->had_error = true;
vm->error_message = malloc(256);
snprintf(vm->error_message, 256, "Method not found: %s.%s", class_name, method_name);
vm->error_message = malloc(RAVA_ERROR_BUFFER_SIZE);
snprintf(vm->error_message, RAVA_ERROR_BUFFER_SIZE, "Method not found: %s.%s", class_name, method_name);
return false;
}
+8 -1
View File
@@ -119,7 +119,7 @@ typedef struct {
int current;
} RavaStringPool_t;
#define RAVA_INTERN_TABLE_SIZE 256
#define RAVA_INTERN_TABLE_SIZE 1024
typedef struct {
char *strings[RAVA_INTERN_TABLE_SIZE];
@@ -209,6 +209,10 @@ RavaArray_t* rava_array_create(RavaValueType_e element_type, size_t length);
void rava_array_destroy(RavaArray_t *array);
void rava_array_set_int(RavaArray_t *array, size_t index, int32_t value);
int32_t rava_array_get_int(RavaArray_t *array, size_t index);
void rava_array_set_long(RavaArray_t *array, size_t index, int64_t value);
int64_t rava_array_get_long(RavaArray_t *array, size_t index);
void rava_array_set_double(RavaArray_t *array, size_t index, double value);
double rava_array_get_double(RavaArray_t *array, size_t index);
void rava_array_set_value(RavaArray_t *array, size_t index, RavaValue_t value);
RavaValue_t rava_array_get_value(RavaArray_t *array, size_t index);
size_t rava_array_length(RavaArray_t *array);
@@ -217,6 +221,9 @@ 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);
int rava_object_get_field_index(RavaObject_t *obj, const char *name);
RavaValue_t rava_object_get_field_by_index(RavaObject_t *obj, int index);
void rava_object_set_field_by_index(RavaObject_t *obj, int index, RavaValue_t value);
RavaStack_t* rava_stack_create(size_t capacity);
void rava_stack_destroy(RavaStack_t *stack);
+101
View File
@@ -0,0 +1,101 @@
#define _POSIX_C_SOURCE 200809L
#include "runtime.h"
#include <stdlib.h>
#include <stdio.h>
#define RAVA_MAX_ARRAY_LENGTH 1000000
RavaArray_t* rava_array_create(RavaValueType_e element_type, size_t length) {
if (length > RAVA_MAX_ARRAY_LENGTH) {
fprintf(stderr, "Warning: Array size %zu exceeds maximum %d, clamping\n",
length, RAVA_MAX_ARRAY_LENGTH);
length = RAVA_MAX_ARRAY_LENGTH;
}
RavaArray_t *array = malloc(sizeof(RavaArray_t));
if (!array) return NULL;
array->element_type = element_type;
array->length = length;
array->data = NULL;
switch (element_type) {
case RAVA_VAL_INT:
array->data = calloc(length, sizeof(int32_t));
break;
case RAVA_VAL_LONG:
array->data = calloc(length, sizeof(int64_t));
break;
case RAVA_VAL_DOUBLE:
array->data = calloc(length, sizeof(double));
break;
case RAVA_VAL_BOOLEAN:
array->data = calloc(length, sizeof(bool));
break;
case RAVA_VAL_ARRAY:
case RAVA_VAL_OBJECT:
array->data = calloc(length, sizeof(RavaValue_t));
break;
default:
array->data = calloc(length, sizeof(void*));
break;
}
if (!array->data && length > 0) {
free(array);
return NULL;
}
return array;
}
void rava_array_destroy(RavaArray_t *array) {
if (!array) return;
free(array->data);
free(array);
}
void rava_array_set_int(RavaArray_t *array, size_t index, int32_t value) {
if (!array || !array->data || index >= array->length) return;
((int32_t*)array->data)[index] = value;
}
int32_t rava_array_get_int(RavaArray_t *array, size_t index) {
if (!array || !array->data || index >= array->length) return 0;
return ((int32_t*)array->data)[index];
}
void rava_array_set_long(RavaArray_t *array, size_t index, int64_t value) {
if (!array || !array->data || index >= array->length) return;
((int64_t*)array->data)[index] = value;
}
int64_t rava_array_get_long(RavaArray_t *array, size_t index) {
if (!array || !array->data || index >= array->length) return 0;
return ((int64_t*)array->data)[index];
}
void rava_array_set_double(RavaArray_t *array, size_t index, double value) {
if (!array || !array->data || index >= array->length) return;
((double*)array->data)[index] = value;
}
double rava_array_get_double(RavaArray_t *array, size_t index) {
if (!array || !array->data || index >= array->length) return 0.0;
return ((double*)array->data)[index];
}
void rava_array_set_value(RavaArray_t *array, size_t index, RavaValue_t value) {
if (!array || !array->data || index >= array->length) return;
((RavaValue_t*)array->data)[index] = value;
}
RavaValue_t rava_array_get_value(RavaArray_t *array, size_t index) {
if (!array || !array->data || index >= array->length) return rava_value_null();
return ((RavaValue_t*)array->data)[index];
}
size_t rava_array_length(RavaArray_t *array) {
if (!array) return 0;
return array->length;
}
+133
View File
@@ -0,0 +1,133 @@
#define _POSIX_C_SOURCE 200809L
#include "runtime.h"
#include "../utils/safe_alloc.h"
#include <stdlib.h>
#include <string.h>
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;
}
RavaObject_t* rava_object_create(const char *class_name) {
RavaObject_t *obj = calloc(1, sizeof(RavaObject_t));
if (!obj) return NULL;
obj->class_name = strdup(class_name);
obj->field_capacity = 8;
obj->field_names = calloc(obj->field_capacity, sizeof(char*));
obj->field_values = calloc(obj->field_capacity, sizeof(RavaValue_t));
if (!obj->field_names || !obj->field_values) {
free(obj->field_names);
free(obj->field_values);
free(obj->class_name);
free(obj);
return NULL;
}
obj->field_count = 0;
for (int i = 0; i < RAVA_OBJECT_HASH_SIZE; i++) {
obj->field_hash[i] = -1;
}
return obj;
}
void rava_object_destroy(RavaObject_t *obj) {
if (!obj) return;
free(obj->class_name);
for (size_t i = 0; i < obj->field_count; i++) {
free(obj->field_names[i]);
}
free(obj->field_names);
free(obj->field_values);
free(obj);
}
void rava_object_set_field(RavaObject_t *obj, const char *name, RavaValue_t value) {
if (!obj || !name) return;
uint32_t hash = _rava_field_hash(name);
for (size_t probe = 0; probe < RAVA_OBJECT_HASH_SIZE; probe++) {
uint32_t idx = (hash + probe) & (RAVA_OBJECT_HASH_SIZE - 1);
int field_idx = obj->field_hash[idx];
if (field_idx == -1) {
if (obj->field_count >= obj->field_capacity) {
size_t new_cap = obj->field_capacity * 2;
char **new_names = rava_safe_realloc(obj->field_names, new_cap * sizeof(char*));
RavaValue_t *new_values = rava_safe_realloc(obj->field_values, new_cap * sizeof(RavaValue_t));
if (!new_names || !new_values) return;
obj->field_names = new_names;
obj->field_values = new_values;
obj->field_capacity = new_cap;
}
obj->field_names[obj->field_count] = strdup(name);
obj->field_values[obj->field_count] = value;
obj->field_hash[idx] = (int)obj->field_count;
obj->field_count++;
return;
}
if ((size_t)field_idx < obj->field_count &&
strcmp(obj->field_names[field_idx], name) == 0) {
obj->field_values[field_idx] = value;
return;
}
}
}
RavaValue_t rava_object_get_field(RavaObject_t *obj, const char *name) {
if (!obj || !name) return rava_value_null();
uint32_t hash = _rava_field_hash(name);
for (size_t probe = 0; probe < RAVA_OBJECT_HASH_SIZE; probe++) {
uint32_t idx = (hash + probe) & (RAVA_OBJECT_HASH_SIZE - 1);
int field_idx = obj->field_hash[idx];
if (field_idx == -1) {
return rava_value_null();
}
if ((size_t)field_idx < obj->field_count &&
strcmp(obj->field_names[field_idx], name) == 0) {
return obj->field_values[field_idx];
}
}
return rava_value_null();
}
int rava_object_get_field_index(RavaObject_t *obj, const char *name) {
if (!obj || !name) return -1;
uint32_t hash = _rava_field_hash(name);
for (size_t probe = 0; probe < RAVA_OBJECT_HASH_SIZE; probe++) {
uint32_t idx = (hash + probe) & (RAVA_OBJECT_HASH_SIZE - 1);
int field_idx = obj->field_hash[idx];
if (field_idx == -1) return -1;
if ((size_t)field_idx < obj->field_count &&
strcmp(obj->field_names[field_idx], name) == 0) {
return field_idx;
}
}
return -1;
}
RavaValue_t rava_object_get_field_by_index(RavaObject_t *obj, int index) {
if (!obj || index < 0 || (size_t)index >= obj->field_count) {
return rava_value_null();
}
return obj->field_values[index];
}
void rava_object_set_field_by_index(RavaObject_t *obj, int index, RavaValue_t value) {
if (!obj || index < 0 || (size_t)index >= obj->field_count) return;
obj->field_values[index] = value;
}
+137
View File
@@ -1,4 +1,5 @@
#include "superinst.h"
#include "fastframe.h"
#include <string.h>
static void optimize_inc_dec_local(RavaInstruction_t *instrs, size_t count) {
@@ -135,12 +136,148 @@ static void optimize_local_lt_local_jump(RavaInstruction_t *instrs, size_t count
}
}
static int is_power_of_two(int64_t n) {
return n > 0 && (n & (n - 1)) == 0;
}
static int log2_int(int64_t n) {
int result = 0;
while (n > 1) {
n >>= 1;
result++;
}
return result;
}
static void optimize_strength_reduction(RavaInstruction_t *instrs, size_t count) {
for (size_t i = 0; i + 2 < count; i++) {
if (instrs[i+1].opcode == RAVA_OP_LOAD_CONST) {
int64_t const_val = instrs[i+1].operand.int_value;
if (instrs[i+2].opcode == RAVA_OP_MUL && is_power_of_two(const_val)) {
int shift_amount = log2_int(const_val);
instrs[i+1].operand.int_value = shift_amount;
instrs[i+2].opcode = RAVA_OP_SHL;
}
else if (instrs[i+2].opcode == RAVA_OP_DIV && is_power_of_two(const_val)) {
int shift_amount = log2_int(const_val);
instrs[i+1].operand.int_value = shift_amount;
instrs[i+2].opcode = RAVA_OP_SHR;
}
else if (instrs[i+2].opcode == RAVA_OP_MOD && const_val == 2) {
instrs[i+1].operand.int_value = 1;
instrs[i+2].opcode = RAVA_OP_AND;
}
}
}
}
static void optimize_constant_folding(RavaInstruction_t *instrs, size_t count) {
for (size_t i = 0; i + 2 < count; i++) {
if (instrs[i].opcode == RAVA_OP_LOAD_CONST &&
instrs[i+1].opcode == RAVA_OP_LOAD_CONST) {
int64_t val1 = instrs[i].operand.int_value;
int64_t val2 = instrs[i+1].operand.int_value;
int64_t result = 0;
int can_fold = 1;
switch (instrs[i+2].opcode) {
case RAVA_OP_ADD:
result = val1 + val2;
break;
case RAVA_OP_SUB:
result = val1 - val2;
break;
case RAVA_OP_MUL:
result = val1 * val2;
break;
case RAVA_OP_DIV:
if (val2 != 0) {
result = val1 / val2;
} else {
can_fold = 0;
}
break;
case RAVA_OP_MOD:
if (val2 != 0) {
result = val1 % val2;
} else {
can_fold = 0;
}
break;
case RAVA_OP_AND:
result = val1 & val2;
break;
case RAVA_OP_OR:
result = val1 | val2;
break;
case RAVA_OP_XOR:
result = val1 ^ val2;
break;
case RAVA_OP_SHL:
result = val1 << val2;
break;
case RAVA_OP_SHR:
result = val1 >> val2;
break;
case RAVA_OP_EQ:
result = val1 == val2;
break;
case RAVA_OP_NE:
result = val1 != val2;
break;
case RAVA_OP_LT:
result = val1 < val2;
break;
case RAVA_OP_LE:
result = val1 <= val2;
break;
case RAVA_OP_GT:
result = val1 > val2;
break;
case RAVA_OP_GE:
result = val1 >= val2;
break;
default:
can_fold = 0;
break;
}
if (can_fold) {
instrs[i].operand.int_value = result;
instrs[i+1].opcode = RAVA_OP_NOP;
instrs[i+2].opcode = RAVA_OP_NOP;
}
}
}
}
static void optimize_inline_calls(RavaInstruction_t *instrs, size_t count) {
for (size_t i = 0; i < count; i++) {
if (instrs[i].opcode == RAVA_OP_CALL_STATIC ||
instrs[i].opcode == RAVA_OP_CALL_RECURSIVE) {
RavaMethod_t *target = (RavaMethod_t*)instrs[i].operand.call.cached_method;
if (target && target->is_simple && target->is_leaf &&
target->local_count <= RAVA_INLINE_FRAME_LOCALS &&
target->max_stack <= RAVA_INLINE_FRAME_STACK) {
instrs[i].opcode = RAVA_OP_CALL_INLINE;
}
}
}
}
void rava_optimize_superinstructions(RavaMethod_t* method) {
if (!method || !method->instructions) return;
RavaInstruction_t *instrs = method->instructions->instructions;
size_t count = method->instructions->count;
optimize_constant_folding(instrs, count);
optimize_inline_calls(instrs, count);
optimize_strength_reduction(instrs, count);
optimize_add_local_to_local(instrs, count);
optimize_local_lt_local_jump(instrs, count);
optimize_inc_dec_local(instrs, count);