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:
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user