Power up./plot.py

This commit is contained in:
retoor 2025-12-04 06:14:22 +01:00
parent c8fe57191c
commit e1ddf91281
18 changed files with 930 additions and 236 deletions

View File

@ -17,7 +17,7 @@ SEMANTIC_OBJECTS = $(SEMANTIC_SOURCES:.c=.o)
IR_SOURCES = ir/ir.c ir/ir_gen.c
IR_OBJECTS = $(IR_SOURCES:.c=.o)
RUNTIME_SOURCES = runtime/runtime.c runtime/labeltable.c runtime/methodcache.c runtime/fastframe.c runtime/superinst.c
RUNTIME_SOURCES = runtime/runtime.c runtime/runtime_array.c runtime/runtime_object.c runtime/labeltable.c runtime/methodcache.c runtime/fastframe.c runtime/superinst.c
RUNTIME_OBJECTS = $(RUNTIME_SOURCES:.c=.o)
PHASE0_SOURCES = runtime/fastframe.c runtime/labeltable.c runtime/methodcache.c
@ -98,7 +98,10 @@ TEST_MULTIDIM_ARRAYS_OBJECTS = $(TEST_MULTIDIM_ARRAYS_SOURCES:.c=.o)
TEST_STATIC_INIT_SOURCES = tests/test_static_init.c
TEST_STATIC_INIT_OBJECTS = $(TEST_STATIC_INIT_SOURCES:.c=.o)
all: test_lexer test_parser test_semantic test_ir test_runtime test_strings test_arrays test_objects test_instance_methods test_fileio test_dowhile test_switch test_math test_string_methods test_static test_interfaces test_exceptions test_ternary test_bitwise test_enhanced_for test_array_init test_instanceof test_shortcircuit test_multidim_arrays test_static_init
TEST_NEGATIVE_SOURCES = tests/test_negative.c
TEST_NEGATIVE_OBJECTS = $(TEST_NEGATIVE_SOURCES:.c=.o)
all: test_lexer test_parser test_semantic test_ir test_runtime test_strings test_arrays test_objects test_instance_methods test_fileio test_dowhile test_switch test_math test_string_methods test_static test_interfaces test_exceptions test_ternary test_bitwise test_enhanced_for test_array_init test_instanceof test_shortcircuit test_multidim_arrays test_static_init test_negative
test_lexer: $(LEXER_OBJECTS) $(TEST_LEXER_OBJECTS)
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
@ -175,6 +178,9 @@ test_multidim_arrays: $(LEXER_OBJECTS) $(PARSER_OBJECTS) $(TYPES_OBJECTS) $(SEMA
test_static_init: $(LEXER_OBJECTS) $(PARSER_OBJECTS) $(TYPES_OBJECTS) $(SEMANTIC_OBJECTS) $(IR_OBJECTS) $(RUNTIME_OBJECTS) $(TEST_STATIC_INIT_OBJECTS)
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
test_negative: $(LEXER_OBJECTS) $(PARSER_OBJECTS) $(TYPES_OBJECTS) $(SEMANTIC_OBJECTS) $(IR_OBJECTS) $(RUNTIME_OBJECTS) $(TEST_NEGATIVE_OBJECTS)
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
@ -240,8 +246,8 @@ clean:
$(PHASE0_OBJECTS) \
$(TEST_LEXER_OBJECTS) $(TEST_PARSER_OBJECTS) $(TEST_SEMANTIC_OBJECTS) $(TEST_IR_OBJECTS) $(TEST_RUNTIME_OBJECTS) \
$(TEST_STRINGS_OBJECTS) $(TEST_ARRAYS_OBJECTS) $(TEST_OBJECTS_OBJECTS) $(TEST_INSTANCE_OBJECTS) $(TEST_FILEIO_OBJECTS) \
$(TEST_DOWHILE_OBJECTS) $(TEST_SWITCH_OBJECTS) $(TEST_MATH_OBJECTS) $(TEST_STRING_METHODS_OBJECTS) $(TEST_STATIC_OBJECTS) $(TEST_INTERFACES_OBJECTS) $(TEST_EXCEPTIONS_OBJECTS) $(TEST_TERNARY_OBJECTS) $(TEST_BITWISE_OBJECTS) $(TEST_ENHANCED_FOR_OBJECTS) $(TEST_ARRAY_INIT_OBJECTS) $(TEST_INSTANCEOF_OBJECTS) $(TEST_SHORTCIRCUIT_OBJECTS) $(TEST_MULTIDIM_ARRAYS_OBJECTS) $(TEST_STATIC_INIT_OBJECTS) $(TEST_BENCHMARK_OBJECTS) \
test_lexer test_parser test_semantic test_ir test_runtime test_strings test_arrays test_objects test_instance_methods test_fileio test_dowhile test_switch test_math test_string_methods test_static test_interfaces test_exceptions test_ternary test_bitwise test_enhanced_for test_array_init test_instanceof test_shortcircuit test_multidim_arrays test_static_init test_benchmark \
$(TEST_DOWHILE_OBJECTS) $(TEST_SWITCH_OBJECTS) $(TEST_MATH_OBJECTS) $(TEST_STRING_METHODS_OBJECTS) $(TEST_STATIC_OBJECTS) $(TEST_INTERFACES_OBJECTS) $(TEST_EXCEPTIONS_OBJECTS) $(TEST_TERNARY_OBJECTS) $(TEST_BITWISE_OBJECTS) $(TEST_ENHANCED_FOR_OBJECTS) $(TEST_ARRAY_INIT_OBJECTS) $(TEST_INSTANCEOF_OBJECTS) $(TEST_SHORTCIRCUIT_OBJECTS) $(TEST_MULTIDIM_ARRAYS_OBJECTS) $(TEST_STATIC_INIT_OBJECTS) $(TEST_NEGATIVE_OBJECTS) $(TEST_BENCHMARK_OBJECTS) \
test_lexer test_parser test_semantic test_ir test_runtime test_strings test_arrays test_objects test_instance_methods test_fileio test_dowhile test_switch test_math test_string_methods test_static test_interfaces test_exceptions test_ternary test_bitwise test_enhanced_for test_array_init test_instanceof test_shortcircuit test_multidim_arrays test_static_init test_negative test_benchmark \
test_nanbox test_fastframe test_labeltable test_methodcache test_benchmark_pgo *.gcda */*.gcda
.PHONY: all clean benchmark test_phase0 pgo test_benchmark_pgo_gen pgo_run test_benchmark_pgo test
@ -253,5 +259,5 @@ test: all
./test_fileio && ./test_dowhile && ./test_switch && ./test_math && ./test_string_methods && \
./test_static && ./test_interfaces && ./test_exceptions && ./test_ternary && \
./test_bitwise && ./test_enhanced_for && ./test_array_init && ./test_instanceof && \
./test_shortcircuit && ./test_multidim_arrays && ./test_static_init && \
./test_shortcircuit && ./test_multidim_arrays && ./test_static_init && ./test_negative && \
echo "" && echo "=== All Tests Passed ==="

37
ir/ir.c
View File

@ -1,6 +1,7 @@
#define _POSIX_C_SOURCE 200809L
#include "ir.h"
#include "../runtime/labeltable.h"
#include "../utils/safe_alloc.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
@ -23,8 +24,10 @@ void rava_instruction_list_destroy(RavaInstructionList_t *list) {
void rava_instruction_list_add(RavaInstructionList_t *list, RavaInstruction_t instr) {
if (list->count >= list->capacity) {
list->capacity *= 2;
list->instructions = realloc(list->instructions,
RavaInstruction_t *new_instrs = rava_safe_realloc(list->instructions,
sizeof(RavaInstruction_t) * list->capacity);
if (!new_instrs) return;
list->instructions = new_instrs;
}
list->instructions[list->count++] = instr;
}
@ -89,7 +92,9 @@ void rava_class_destroy(RavaClass_t *class) {
void rava_class_add_method(RavaClass_t *class, RavaMethod_t *method) {
if (class->method_count >= class->method_capacity) {
size_t new_capacity = class->method_capacity == 0 ? 4 : class->method_capacity * 2;
class->methods = realloc(class->methods, sizeof(RavaMethod_t*) * new_capacity);
RavaMethod_t **new_methods = rava_safe_realloc(class->methods, sizeof(RavaMethod_t*) * new_capacity);
if (!new_methods) return;
class->methods = new_methods;
class->method_capacity = new_capacity;
}
uint32_t h = _method_hash(method->name);
@ -117,7 +122,9 @@ void rava_program_destroy(RavaProgram_t *program) {
void rava_program_add_class(RavaProgram_t *program, RavaClass_t *class) {
if (program->class_count >= program->class_capacity) {
size_t new_capacity = program->class_capacity == 0 ? 4 : program->class_capacity * 2;
program->classes = realloc(program->classes, sizeof(RavaClass_t*) * new_capacity);
RavaClass_t **new_classes = rava_safe_realloc(program->classes, sizeof(RavaClass_t*) * new_capacity);
if (!new_classes) return;
program->classes = new_classes;
program->class_capacity = new_capacity;
}
program->classes[program->class_count++] = class;
@ -181,6 +188,26 @@ static void _compute_max_stack(RavaMethod_t *method) {
method->max_stack = max_depth + 16;
}
static void _mark_simple_methods(RavaMethod_t *method) {
if (!method || !method->instructions) return;
method->is_leaf = true;
method->is_simple = (method->instructions->count < 20);
for (size_t i = 0; i < method->instructions->count; i++) {
RavaOpCode_e op = method->instructions->instructions[i].opcode;
if (op == RAVA_OP_CALL || op == RAVA_OP_CALL_STATIC ||
op == RAVA_OP_CALL_RECURSIVE || op == RAVA_OP_CALL_VIRTUAL) {
method->is_leaf = false;
method->is_simple = false;
}
if (op == RAVA_OP_JUMP || op == RAVA_OP_JUMP_IF_TRUE ||
op == RAVA_OP_JUMP_IF_FALSE) {
method->is_simple = false;
}
}
}
void rava_program_prebuild_label_tables(RavaProgram_t *program) {
if (!program) return;
for (size_t i = 0; i < program->class_count; i++) {
@ -193,6 +220,7 @@ void rava_program_prebuild_label_tables(RavaProgram_t *program) {
if (method->max_stack == 0) {
_compute_max_stack(method);
}
_mark_simple_methods(method);
}
}
}
@ -222,6 +250,7 @@ static const char* _rava_opcode_name(RavaOpCode_e opcode) {
case RAVA_OP_CALL: return "CALL";
case RAVA_OP_CALL_STATIC: return "CALL_STATIC";
case RAVA_OP_CALL_RECURSIVE: return "CALL_RECURSIVE";
case RAVA_OP_CALL_INLINE: return "CALL_INLINE";
case RAVA_OP_RETURN: return "RETURN";
case RAVA_OP_RETURN_VOID: return "RETURN_VOID";
case RAVA_OP_NEW: return "NEW";
@ -229,7 +258,9 @@ static const char* _rava_opcode_name(RavaOpCode_e opcode) {
case RAVA_OP_NEW_ARRAY_OF_ARRAYS: return "NEW_ARRAY_OF_ARRAYS";
case RAVA_OP_ARRAY_LENGTH: return "ARRAY_LENGTH";
case RAVA_OP_LOAD_ARRAY: return "LOAD_ARRAY";
case RAVA_OP_LOAD_ARRAY_UNCHECKED: return "LOAD_ARRAY_UNCHECKED";
case RAVA_OP_STORE_ARRAY: return "STORE_ARRAY";
case RAVA_OP_STORE_ARRAY_UNCHECKED: return "STORE_ARRAY_UNCHECKED";
case RAVA_OP_POP: return "POP";
case RAVA_OP_DUP: return "DUP";
case RAVA_OP_PRINT: return "PRINT";

View File

@ -17,11 +17,13 @@ typedef enum {
RAVA_OP_LOAD_FIELD,
RAVA_OP_LOAD_STATIC,
RAVA_OP_LOAD_ARRAY,
RAVA_OP_LOAD_ARRAY_UNCHECKED,
RAVA_OP_STORE_LOCAL,
RAVA_OP_STORE_FIELD,
RAVA_OP_STORE_STATIC,
RAVA_OP_STORE_ARRAY,
RAVA_OP_STORE_ARRAY_UNCHECKED,
RAVA_OP_ADD,
RAVA_OP_SUB,
@ -54,6 +56,7 @@ typedef enum {
RAVA_OP_CALL,
RAVA_OP_CALL_STATIC,
RAVA_OP_CALL_RECURSIVE,
RAVA_OP_CALL_INLINE,
RAVA_OP_CALL_VIRTUAL,
RAVA_OP_CALL_SUPER,
RAVA_OP_CALL_NATIVE,
@ -196,6 +199,8 @@ typedef struct {
int max_stack;
RavaInstructionList_t *instructions;
struct LabelTable_s *label_table;
bool is_leaf;
bool is_simple;
} RavaMethod_t;
#define RAVA_METHOD_HASH_SIZE 16

View File

@ -245,7 +245,20 @@ static void _rava_ir_gen_expression(RavaIRGenerator_t *gen, RavaASTNode_t *expr)
_rava_ir_gen_expression(gen, expr->data.assign.target->data.array_access.array);
_rava_ir_gen_expression(gen, expr->data.assign.target->data.array_access.index);
_rava_ir_gen_expression(gen, expr->data.assign.value);
instr.opcode = RAVA_OP_STORE_ARRAY;
bool use_unchecked = false;
if (gen->loop_context && gen->loop_context->has_bounds_check) {
RavaASTNode_t *index_node = expr->data.assign.target->data.array_access.index;
if (index_node->type == RAVA_AST_IDENTIFIER_EXPR) {
const char *index_name = index_node->data.identifier.name;
if (gen->loop_context->loop_var_name &&
strcmp(index_name, gen->loop_context->loop_var_name) == 0) {
use_unchecked = true;
}
}
}
instr.opcode = use_unchecked ? RAVA_OP_STORE_ARRAY_UNCHECKED : RAVA_OP_STORE_ARRAY;
_rava_ir_emit(gen, instr);
} else if (expr->data.assign.target->type == RAVA_AST_MEMBER_ACCESS_EXPR) {
RavaASTNode_t *target_member = expr->data.assign.target;
@ -302,12 +315,25 @@ static void _rava_ir_gen_expression(RavaIRGenerator_t *gen, RavaASTNode_t *expr)
_rava_ir_emit(gen, instr);
break;
case RAVA_AST_ARRAY_ACCESS_EXPR:
case RAVA_AST_ARRAY_ACCESS_EXPR: {
_rava_ir_gen_expression(gen, expr->data.array_access.array);
_rava_ir_gen_expression(gen, expr->data.array_access.index);
instr.opcode = RAVA_OP_LOAD_ARRAY;
bool use_unchecked = false;
if (gen->loop_context && gen->loop_context->has_bounds_check) {
if (expr->data.array_access.index->type == RAVA_AST_IDENTIFIER_EXPR) {
const char *index_name = expr->data.array_access.index->data.identifier.name;
if (gen->loop_context->loop_var_name &&
strcmp(index_name, gen->loop_context->loop_var_name) == 0) {
use_unchecked = true;
}
}
}
instr.opcode = use_unchecked ? RAVA_OP_LOAD_ARRAY_UNCHECKED : RAVA_OP_LOAD_ARRAY;
_rava_ir_emit(gen, instr);
break;
}
case RAVA_AST_NEW_EXPR:
if (expr->data.new_expr.type && expr->data.new_expr.type->data.type.is_array) {
@ -886,7 +912,14 @@ static void _rava_ir_gen_statement(RavaIRGenerator_t *gen, RavaASTNode_t *stmt)
int start_label = rava_instruction_list_new_label(gen->current_method->instructions);
int end_label = rava_instruction_list_new_label(gen->current_method->instructions);
RavaLoopContext_t loop_ctx = { .break_label = end_label, .continue_label = start_label, .parent = gen->loop_context };
RavaLoopContext_t loop_ctx = {
.break_label = end_label,
.continue_label = start_label,
.parent = gen->loop_context,
.loop_var_name = NULL,
.loop_var_index = -1,
.has_bounds_check = false
};
gen->loop_context = &loop_ctx;
instr.opcode = RAVA_OP_LABEL;
@ -917,7 +950,14 @@ static void _rava_ir_gen_statement(RavaIRGenerator_t *gen, RavaASTNode_t *stmt)
int start_label = rava_instruction_list_new_label(gen->current_method->instructions);
int end_label = rava_instruction_list_new_label(gen->current_method->instructions);
RavaLoopContext_t loop_ctx = { .break_label = end_label, .continue_label = start_label, .parent = gen->loop_context };
RavaLoopContext_t loop_ctx = {
.break_label = end_label,
.continue_label = start_label,
.parent = gen->loop_context,
.loop_var_name = NULL,
.loop_var_index = -1,
.has_bounds_check = false
};
gen->loop_context = &loop_ctx;
instr.opcode = RAVA_OP_LABEL;
@ -941,6 +981,33 @@ static void _rava_ir_gen_statement(RavaIRGenerator_t *gen, RavaASTNode_t *stmt)
}
case RAVA_AST_FOR_STMT: {
char *loop_var_name = NULL;
int loop_var_index = -1;
bool has_bounds_check = false;
if (stmt->data.for_stmt.init && stmt->data.for_stmt.init->type == RAVA_AST_VAR_DECL) {
RavaASTNode_t *var_decl = stmt->data.for_stmt.init;
loop_var_name = var_decl->data.var_decl.name;
loop_var_index = (int)gen->next_local;
if (var_decl->data.var_decl.initializer &&
var_decl->data.var_decl.initializer->type == RAVA_AST_LITERAL_EXPR &&
var_decl->data.var_decl.initializer->data.literal.value.int_value == 0) {
if (stmt->data.for_stmt.condition &&
stmt->data.for_stmt.condition->type == RAVA_AST_BINARY_EXPR &&
(stmt->data.for_stmt.condition->data.binary.op == RAVA_BINOP_LT ||
stmt->data.for_stmt.condition->data.binary.op == RAVA_BINOP_LE)) {
RavaASTNode_t *left = stmt->data.for_stmt.condition->data.binary.left;
if (left->type == RAVA_AST_IDENTIFIER_EXPR &&
strcmp(left->data.identifier.name, loop_var_name) == 0) {
has_bounds_check = true;
}
}
}
}
if (stmt->data.for_stmt.init) {
if (stmt->data.for_stmt.init->type == RAVA_AST_VAR_DECL) {
_rava_ir_gen_statement(gen, stmt->data.for_stmt.init);
@ -955,7 +1022,14 @@ static void _rava_ir_gen_statement(RavaIRGenerator_t *gen, RavaASTNode_t *stmt)
int continue_label = rava_instruction_list_new_label(gen->current_method->instructions);
int end_label = rava_instruction_list_new_label(gen->current_method->instructions);
RavaLoopContext_t loop_ctx = { .break_label = end_label, .continue_label = continue_label, .parent = gen->loop_context };
RavaLoopContext_t loop_ctx = {
.break_label = end_label,
.continue_label = continue_label,
.parent = gen->loop_context,
.loop_var_name = loop_var_name,
.loop_var_index = loop_var_index,
.has_bounds_check = has_bounds_check
};
gen->loop_context = &loop_ctx;
instr.opcode = RAVA_OP_LABEL;
@ -1012,7 +1086,14 @@ static void _rava_ir_gen_statement(RavaIRGenerator_t *gen, RavaASTNode_t *stmt)
int continue_label = rava_instruction_list_new_label(gen->current_method->instructions);
int end_label = rava_instruction_list_new_label(gen->current_method->instructions);
RavaLoopContext_t loop_ctx = { .break_label = end_label, .continue_label = continue_label, .parent = gen->loop_context };
RavaLoopContext_t loop_ctx = {
.break_label = end_label,
.continue_label = continue_label,
.parent = gen->loop_context,
.loop_var_name = NULL,
.loop_var_index = (int)idx_local,
.has_bounds_check = true
};
gen->loop_context = &loop_ctx;
instr.opcode = RAVA_OP_LABEL;
@ -1113,7 +1194,14 @@ static void _rava_ir_gen_statement(RavaIRGenerator_t *gen, RavaASTNode_t *stmt)
case RAVA_AST_SWITCH_STMT: {
int end_label = rava_instruction_list_new_label(gen->current_method->instructions);
RavaLoopContext_t switch_ctx = { .break_label = end_label, .continue_label = -1, .parent = gen->loop_context };
RavaLoopContext_t switch_ctx = {
.break_label = end_label,
.continue_label = -1,
.parent = gen->loop_context,
.loop_var_name = NULL,
.loop_var_index = -1,
.has_bounds_check = false
};
gen->loop_context = &switch_ctx;
size_t case_count = stmt->children_count;

View File

@ -15,6 +15,9 @@ typedef struct RavaLoopContext_t {
int break_label;
int continue_label;
struct RavaLoopContext_t *parent;
char *loop_var_name;
int loop_var_index;
bool has_bounds_check;
} RavaLoopContext_t;
typedef struct {

View File

@ -1,5 +1,6 @@
#define _POSIX_C_SOURCE 200809L
#include "lexer.h"
#include "../utils/safe_alloc.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
@ -73,7 +74,12 @@ RavaToken_t* rava_lexer_parse_string(RavaLexer_t *lexer) {
if (length + 1 >= capacity) {
capacity *= 2;
str = realloc(str, capacity);
char *new_str = rava_safe_realloc(str, capacity);
if (!new_str) {
lexer->error_message = strdup("Out of memory");
return _rava_lexer_create_token(lexer, RAVA_TOKEN_ERROR);
}
str = new_str;
}
str[length++] = c;
}

View File

@ -1,4 +1,5 @@
#include "lexer.h"
#include "../utils/safe_alloc.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
@ -11,6 +12,7 @@ extern RavaToken_t* rava_lexer_parse_number(RavaLexer_t *lexer);
RavaLexer_t* rava_lexer_create(const char *source) {
RavaLexer_t *lexer = malloc(sizeof(RavaLexer_t));
if (!lexer) return NULL;
lexer->source = source;
lexer->source_length = strlen(source);
lexer->current = 0;
@ -116,9 +118,14 @@ void _rava_lexer_skip_whitespace(RavaLexer_t *lexer) {
RavaToken_t* _rava_lexer_create_token(RavaLexer_t *lexer, RavaTokenType_e type) {
RavaToken_t *token = malloc(sizeof(RavaToken_t));
if (!token) return NULL;
token->type = type;
size_t length = lexer->current - lexer->start;
token->lexeme = malloc(length + 1);
if (!token->lexeme) {
free(token);
return NULL;
}
memcpy(token->lexeme, lexer->source + lexer->start, length);
token->lexeme[length] = '\0';
token->line = lexer->line;
@ -312,8 +319,10 @@ RavaToken_t* rava_lexer_next_token(RavaLexer_t *lexer) {
return rava_lexer_parse_character(lexer);
default:
lexer->error_message = malloc(100);
snprintf(lexer->error_message, 100, "Unexpected character '%c'", c);
lexer->error_message = malloc(RAVA_ERROR_BUFFER_SIZE);
if (lexer->error_message) {
snprintf(lexer->error_message, RAVA_ERROR_BUFFER_SIZE, "Unexpected character '%c'", c);
}
return _rava_lexer_create_token(lexer, RAVA_TOKEN_ERROR);
}
}

View File

@ -1,11 +1,13 @@
#define _POSIX_C_SOURCE 200809L
#include "parser.h"
#include "../utils/safe_alloc.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
RavaASTNode_t* rava_ast_node_create(RavaASTNodeType_e type, int line, int column) {
RavaASTNode_t *node = calloc(1, sizeof(RavaASTNode_t));
if (!node) return NULL;
node->type = type;
node->line = line;
node->column = column;
@ -81,7 +83,9 @@ void rava_ast_node_add_child(RavaASTNode_t *parent, RavaASTNode_t *child) {
if (parent->children_count >= parent->children_capacity) {
size_t new_capacity = parent->children_capacity == 0 ? 4 : parent->children_capacity * 2;
parent->children = realloc(parent->children, sizeof(RavaASTNode_t*) * new_capacity);
RavaASTNode_t **new_children = rava_safe_realloc(parent->children, sizeof(RavaASTNode_t*) * new_capacity);
if (!new_children) return;
parent->children = new_children;
parent->children_capacity = new_capacity;
}
@ -91,6 +95,7 @@ void rava_ast_node_add_child(RavaASTNode_t *parent, RavaASTNode_t *child) {
RavaParser_t* rava_parser_create(RavaLexer_t *lexer) {
RavaParser_t *parser = malloc(sizeof(RavaParser_t));
if (!parser) return NULL;
parser->lexer = lexer;
parser->current_token = rava_lexer_next_token(lexer);
parser->peek_token = rava_lexer_next_token(lexer);
@ -134,9 +139,11 @@ bool _rava_parser_expect(RavaParser_t *parser, RavaTokenType_e type, const char
parser->had_error = true;
if (parser->error_message) free(parser->error_message);
parser->error_message = malloc(256);
snprintf(parser->error_message, 256, "%s at line %d, column %d",
parser->error_message = malloc(RAVA_ERROR_BUFFER_SIZE);
if (parser->error_message) {
snprintf(parser->error_message, RAVA_ERROR_BUFFER_SIZE, "%s at line %d, column %d",
message, parser->current_token->line, parser->current_token->column);
}
return false;
}

View File

@ -1,5 +1,6 @@
#define _POSIX_C_SOURCE 200809L
#include "parser.h"
#include "../utils/safe_alloc.h"
#include <stdlib.h>
#include <string.h>
@ -96,13 +97,22 @@ RavaASTNode_t* _rava_parser_parse_class_declaration(RavaParser_t *parser) {
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_IMPLEMENTS)) {
size_t capacity = 4;
class_decl->data.class_decl.interfaces = malloc(capacity * sizeof(char*));
if (!class_decl->data.class_decl.interfaces) {
parser->had_error = true;
return NULL;
}
do {
if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) {
if (class_decl->data.class_decl.interfaces_count >= capacity) {
capacity *= 2;
class_decl->data.class_decl.interfaces = realloc(
char **new_interfaces = rava_safe_realloc(
class_decl->data.class_decl.interfaces,
capacity * sizeof(char*));
if (!new_interfaces) {
parser->had_error = true;
return NULL;
}
class_decl->data.class_decl.interfaces = new_interfaces;
}
class_decl->data.class_decl.interfaces[class_decl->data.class_decl.interfaces_count++] =
strdup(parser->current_token->lexeme);

View File

@ -1,5 +1,6 @@
#define _POSIX_C_SOURCE 200809L
#include "parser.h"
#include "../utils/safe_alloc.h"
#include <stdlib.h>
#include <string.h>
@ -97,6 +98,10 @@ static RavaASTNode_t* _rava_parser_parse_primary(RavaParser_t *parser) {
if (_rava_parser_match(parser, RAVA_TOKEN_LBRACKET)) {
size_t args_capacity = 4;
node->data.new_expr.arguments = malloc(sizeof(RavaASTNode_t*) * args_capacity);
if (!node->data.new_expr.arguments) {
parser->had_error = true;
return NULL;
}
node->data.new_expr.arguments_count = 0;
if (!_rava_parser_check(parser, RAVA_TOKEN_RBRACKET)) {
@ -108,8 +113,13 @@ static RavaASTNode_t* _rava_parser_parse_primary(RavaParser_t *parser) {
while (_rava_parser_match(parser, RAVA_TOKEN_LBRACKET)) {
if (node->data.new_expr.arguments_count >= args_capacity) {
args_capacity *= 2;
node->data.new_expr.arguments = realloc(node->data.new_expr.arguments,
RavaASTNode_t **new_args = rava_safe_realloc(node->data.new_expr.arguments,
sizeof(RavaASTNode_t*) * args_capacity);
if (!new_args) {
parser->had_error = true;
return NULL;
}
node->data.new_expr.arguments = new_args;
}
if (!_rava_parser_check(parser, RAVA_TOKEN_RBRACKET)) {
node->data.new_expr.arguments[node->data.new_expr.arguments_count++] =
@ -129,14 +139,23 @@ static RavaASTNode_t* _rava_parser_parse_primary(RavaParser_t *parser) {
size_t args_capacity = 4;
node->data.new_expr.arguments = malloc(sizeof(RavaASTNode_t*) * args_capacity);
if (!node->data.new_expr.arguments) {
parser->had_error = true;
return NULL;
}
node->data.new_expr.arguments_count = 0;
if (!_rava_parser_check(parser, RAVA_TOKEN_RPAREN)) {
do {
if (node->data.new_expr.arguments_count >= args_capacity) {
args_capacity *= 2;
node->data.new_expr.arguments = realloc(node->data.new_expr.arguments,
RavaASTNode_t **new_args = rava_safe_realloc(node->data.new_expr.arguments,
sizeof(RavaASTNode_t*) * args_capacity);
if (!new_args) {
parser->had_error = true;
return NULL;
}
node->data.new_expr.arguments = new_args;
}
node->data.new_expr.arguments[node->data.new_expr.arguments_count++] =
_rava_parser_parse_expression(parser);
@ -173,14 +192,23 @@ static RavaASTNode_t* _rava_parser_parse_postfix(RavaParser_t *parser) {
size_t args_capacity = 4;
call->data.call.arguments = malloc(sizeof(RavaASTNode_t*) * args_capacity);
if (!call->data.call.arguments) {
parser->had_error = true;
return NULL;
}
call->data.call.arguments_count = 0;
if (!_rava_parser_check(parser, RAVA_TOKEN_RPAREN)) {
do {
if (call->data.call.arguments_count >= args_capacity) {
args_capacity *= 2;
call->data.call.arguments = realloc(call->data.call.arguments,
RavaASTNode_t **new_args = rava_safe_realloc(call->data.call.arguments,
sizeof(RavaASTNode_t*) * args_capacity);
if (!new_args) {
parser->had_error = true;
return NULL;
}
call->data.call.arguments = new_args;
}
call->data.call.arguments[call->data.call.arguments_count++] =
_rava_parser_parse_expression(parser);
@ -576,14 +604,23 @@ RavaASTNode_t* _rava_parser_parse_array_initializer(RavaParser_t *parser) {
size_t capacity = 8;
node->data.array_init.elements = malloc(sizeof(RavaASTNode_t*) * capacity);
if (!node->data.array_init.elements) {
parser->had_error = true;
return NULL;
}
node->data.array_init.elements_count = 0;
if (!_rava_parser_check(parser, RAVA_TOKEN_RBRACE)) {
do {
if (node->data.array_init.elements_count >= capacity) {
capacity *= 2;
node->data.array_init.elements = realloc(node->data.array_init.elements,
RavaASTNode_t **new_elements = rava_safe_realloc(node->data.array_init.elements,
sizeof(RavaASTNode_t*) * capacity);
if (!new_elements) {
parser->had_error = true;
return NULL;
}
node->data.array_init.elements = new_elements;
}
node->data.array_init.elements[node->data.array_init.elements_count++] =
_rava_parser_parse_expression(parser);

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;

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;
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) {
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));
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[h] = (int)obj->field_count;
obj->field_hash[idx] = (int)obj->field_count;
obj->field_count++;
return;
}
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];
if ((size_t)field_idx < obj->field_count &&
strcmp(obj->field_names[field_idx], name) == 0) {
obj->field_values[field_idx] = value;
return;
}
}
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,19 +411,21 @@ 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 &&
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;
}
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;
}
}
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;
return;
}
}
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) {
table->capacity *= 2;
table->fields = realloc(table->fields, sizeof(RavaStaticField_t) * 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[h] = (int)table->count;
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;
}
}
}
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;
}

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
runtime/runtime_array.c Normal file
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
runtime/runtime_object.c Normal file
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;
}

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);

View File

@ -1,5 +1,6 @@
#define _POSIX_C_SOURCE 200809L
#include "semantic.h"
#include "../utils/safe_alloc.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
@ -10,7 +11,12 @@ static RavaType_t* _rava_semantic_check_expression(RavaSemanticAnalyzer_t *analy
RavaSemanticAnalyzer_t* rava_semantic_analyzer_create() {
RavaSemanticAnalyzer_t *analyzer = calloc(1, sizeof(RavaSemanticAnalyzer_t));
if (!analyzer) return NULL;
analyzer->symbol_table = rava_symbol_table_create();
if (!analyzer->symbol_table) {
free(analyzer);
return NULL;
}
analyzer->error_message = NULL;
analyzer->had_error = false;
analyzer->error_count = 0;
@ -29,8 +35,9 @@ static void _rava_semantic_error(RavaSemanticAnalyzer_t *analyzer, const char *m
analyzer->error_count++;
if (analyzer->error_message) free(analyzer->error_message);
analyzer->error_message = malloc(512);
snprintf(analyzer->error_message, 512, "Semantic error at line %d, column %d: %s",
analyzer->error_message = malloc(RAVA_ERROR_BUFFER_SIZE);
if (!analyzer->error_message) return;
snprintf(analyzer->error_message, RAVA_ERROR_BUFFER_SIZE, "Semantic error at line %d, column %d: %s",
line, col, message);
}

32
utils/safe_alloc.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef RAVA_SAFE_ALLOC_H
#define RAVA_SAFE_ALLOC_H
#include <stdlib.h>
#include <stdio.h>
#define RAVA_ERROR_BUFFER_SIZE 512
static inline void* rava_safe_realloc(void *ptr, size_t size) {
if (size == 0) {
free(ptr);
return NULL;
}
void *new_ptr = realloc(ptr, size);
if (!new_ptr) {
free(ptr);
return NULL;
}
return new_ptr;
}
static inline void* rava_safe_malloc(size_t size) {
if (size == 0) return NULL;
return malloc(size);
}
static inline void* rava_safe_calloc(size_t count, size_t size) {
if (count == 0 || size == 0) return NULL;
return calloc(count, size);
}
#endif