mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
mruby-compiler: add infrastructure for variable-sized ast nodes
This commit introduces the core infrastructure for variable-sized AST nodes, designed to improve memory efficiency. The previous fixed-size nodes are replaced by nodes that can store data inline, such as strings and integers, reducing pointer indirection and memory overhead. Key changes include: - A generic variable-sized node header (`mrb_ast_var_header`). - A size-class-based memory allocation system for these nodes. - Implementation of variable-sized nodes for core types: symbols, strings, integers, and variables (lvar, gvar, ivar, cvar). - Integration into the parser and code generator, controlled by a feature flag. - Centralized and improved type-casting macros for AST nodes. Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -33,6 +33,7 @@ typedef struct mrb_ccontext {
|
||||
mrb_bool keep_lv:1;
|
||||
mrb_bool no_optimize:1;
|
||||
mrb_bool no_ext_ops:1;
|
||||
mrb_bool use_variable_nodes:1; /* Enable variable-sized AST nodes */
|
||||
const struct RProc *upper;
|
||||
|
||||
size_t parser_nerr;
|
||||
@@ -133,6 +134,11 @@ struct mrb_parser_state {
|
||||
uint16_t filename_table_length;
|
||||
uint16_t current_filename_index;
|
||||
|
||||
/* Variable-sized node management */
|
||||
struct mrb_ast_node *var_free_lists[5]; /* Free lists by size class (SIZE_CLASS_COUNT) */
|
||||
size_t var_alloc_counts[5]; /* Allocation tracking by size class */
|
||||
size_t var_total_allocated; /* Total variable node memory */
|
||||
mrb_bool var_nodes_enabled:1; /* Feature flag for gradual rollout */
|
||||
mrb_ast_node *nvars;
|
||||
};
|
||||
|
||||
|
||||
@@ -2198,14 +2198,15 @@ node_len(node *tree)
|
||||
}
|
||||
|
||||
/* Casts a void* (typically from an AST node part) to an int. */
|
||||
#define nint(x) ((int)(intptr_t)(x))
|
||||
#define node_to_sym(x) ((mrb_sym)(intptr_t)(x))
|
||||
#define node_to_int(x) ((int)(intptr_t)(x))
|
||||
/* Casts a void* (typically from an AST node part) to a char. */
|
||||
#define nchar(x) ((char)(intptr_t)(x))
|
||||
#define node_to_char(x) ((char)(intptr_t)(x))
|
||||
/* Casts a void* (typically from an AST node part) to an mrb_sym. */
|
||||
#define nsym(x) ((mrb_sym)(intptr_t)(x))
|
||||
|
||||
|
||||
/* Extracts the symbol (name) of a local variable from its AST node representation. */
|
||||
#define lv_name(lv) nsym((lv)->car)
|
||||
#define lv_name(lv) node_to_sym((lv)->car)
|
||||
|
||||
/*
|
||||
* Searches for a local variable `id` within the current scope's local variable list (`s->lv`).
|
||||
@@ -2450,7 +2451,7 @@ lambda_body(codegen_scope *s, node *tree, int blk)
|
||||
i = 0;
|
||||
while (opt) { /* Iterate through optional arguments. */
|
||||
int idx;
|
||||
mrb_sym id = nsym(opt->car->car); /* Symbol of the optional argument. */
|
||||
mrb_sym id = node_to_sym(opt->car->car); /* Symbol of the optional argument. */
|
||||
|
||||
dispatch(s, pos+i*3+1); /* Patch the jump to this argument's default value code. */
|
||||
codegen(s, opt->car->cdr, VAL); /* Generate code for the default value expression. */
|
||||
@@ -2477,15 +2478,15 @@ lambda_body(codegen_scope *s, node *tree, int blk)
|
||||
if (tail->cdr->cdr->car) { /* Check if a keyword rest argument exists. */
|
||||
kwrest = 1;
|
||||
}
|
||||
mrb_assert(nint(tail->car) == NODE_ARGS_TAIL);
|
||||
mrb_assert(node_to_int(tail->car) == NODE_ARGS_TAIL);
|
||||
mrb_assert(node_len(tail) == 4);
|
||||
|
||||
while (kwds) {
|
||||
int jmpif_key_p, jmp_def_set = -1;
|
||||
node *kwd = kwds->car, *def_arg = kwd->cdr->cdr->car;
|
||||
mrb_sym kwd_sym = nsym(kwd->cdr->car);
|
||||
mrb_sym kwd_sym = node_to_sym(kwd->cdr->car);
|
||||
|
||||
mrb_assert(nint(kwd->car) == NODE_KW_ARG);
|
||||
mrb_assert(node_to_int(kwd->car) == NODE_KW_ARG);
|
||||
|
||||
if (def_arg) {
|
||||
int idx;
|
||||
@@ -2516,7 +2517,7 @@ lambda_body(codegen_scope *s, node *tree, int blk)
|
||||
}
|
||||
/* Block argument processing */
|
||||
if (ba) { /* If a block argument (e.g., &blk) is present. */
|
||||
mrb_sym bparam = nsym(tail->cdr->cdr->cdr->car); /* Symbol of the block parameter. */
|
||||
mrb_sym bparam = node_to_sym(tail->cdr->cdr->cdr->car); /* Symbol of the block parameter. */
|
||||
pos = ma+oa+ra+pa+(ka||kd); /* Calculate register offset for the block parameter. */
|
||||
if (bparam) { /* If it's a named block parameter. */
|
||||
int idx = lv_idx(s, bparam);
|
||||
@@ -2530,7 +2531,7 @@ lambda_body(codegen_scope *s, node *tree, int blk)
|
||||
node *n = margs;
|
||||
pos = 1; /* Start from register 1 (after self). */
|
||||
while (n) {
|
||||
if (nint(n->car->car) == NODE_MASGN) { /* If the argument is a mass assignment (e.g., |(a,b)| ). */
|
||||
if (node_to_int(n->car->car) == NODE_MASGN) { /* If the argument is a mass assignment (e.g., |(a,b)| ). */
|
||||
gen_massignment(s, n->car->cdr->car, pos, NOVAL);
|
||||
}
|
||||
pos++;
|
||||
@@ -2541,7 +2542,7 @@ lambda_body(codegen_scope *s, node *tree, int blk)
|
||||
node *n = pargs;
|
||||
pos = ma+oa+ra+1; /* Calculate starting register for post-mandatory args. */
|
||||
while (n) {
|
||||
if (nint(n->car->car) == NODE_MASGN) { /* If argument is a mass assignment. */
|
||||
if (node_to_int(n->car->car) == NODE_MASGN) { /* If argument is a mass assignment. */
|
||||
gen_massignment(s, n->car->cdr->car, pos, NOVAL);
|
||||
}
|
||||
pos++;
|
||||
@@ -2614,7 +2615,7 @@ static mrb_bool
|
||||
nosplat(node *t)
|
||||
{
|
||||
while (t) {
|
||||
if (nint(t->car->car) == NODE_SPLAT) return FALSE;
|
||||
if (node_to_int(t->car->car) == NODE_SPLAT) return FALSE;
|
||||
t = t->cdr;
|
||||
}
|
||||
return TRUE;
|
||||
@@ -2668,7 +2669,7 @@ gen_values(codegen_scope *s, node *t, int val, int limit)
|
||||
}
|
||||
|
||||
while (t) {
|
||||
int is_splat = nint(t->car->car) == NODE_SPLAT;
|
||||
int is_splat = node_to_int(t->car->car) == NODE_SPLAT;
|
||||
|
||||
if (is_splat || cursp() >= slimit) { /* flush stack */
|
||||
pop_n(n);
|
||||
@@ -2727,7 +2728,7 @@ gen_hash(codegen_scope *s, node *tree, int val, int limit)
|
||||
mrb_bool first = TRUE;
|
||||
|
||||
while (tree) {
|
||||
if (nint(tree->car->car->car) == NODE_KW_REST_ARGS) {
|
||||
if (node_to_int(tree->car->car->car) == NODE_KW_REST_ARGS) {
|
||||
if (val && first) {
|
||||
genop_2(s, OP_HASH, cursp(), 0);
|
||||
push();
|
||||
@@ -2794,7 +2795,7 @@ gen_hash(codegen_scope *s, node *tree, int val, int limit)
|
||||
static void
|
||||
gen_call(codegen_scope *s, node *tree, int val, int safe)
|
||||
{
|
||||
mrb_sym sym = nsym(tree->cdr->car);
|
||||
mrb_sym sym = node_to_sym(tree->cdr->car);
|
||||
int skip = 0, n = 0, nk = 0, noop = no_optimize(s), noself = 0, blk = 0, sp_save = cursp();
|
||||
enum mrb_insn opt_op = OP_NOP;
|
||||
|
||||
@@ -2811,7 +2812,7 @@ gen_call(codegen_scope *s, node *tree, int val, int safe)
|
||||
else if (sym == MRB_OPSYM_2(s->mrb, aref)) opt_op = OP_GETIDX;
|
||||
else if (sym == MRB_OPSYM_2(s->mrb, aset)) opt_op = OP_SETIDX;
|
||||
}
|
||||
if (!tree->car || (opt_op == OP_NOP && nint(tree->car->car) == NODE_SELF)) {
|
||||
if (!tree->car || (opt_op == OP_NOP && node_to_int(tree->car->car) == NODE_SELF)) {
|
||||
noself = 1;
|
||||
push();
|
||||
}
|
||||
@@ -2900,7 +2901,7 @@ static void
|
||||
gen_assignment(codegen_scope *s, node *tree, node *rhs, int sp, int val)
|
||||
{
|
||||
int idx;
|
||||
int type = nint(tree->car);
|
||||
int type = node_to_int(tree->car);
|
||||
|
||||
switch (type) {
|
||||
case NODE_GVAR:
|
||||
@@ -2938,11 +2939,11 @@ gen_assignment(codegen_scope *s, node *tree, node *rhs, int sp, int val)
|
||||
tree = tree->cdr;
|
||||
switch (type) {
|
||||
case NODE_GVAR:
|
||||
gen_setxv(s, OP_SETGV, sp, nsym(tree), val);
|
||||
gen_setxv(s, OP_SETGV, sp, node_to_sym(tree), val);
|
||||
break;
|
||||
case NODE_ARG:
|
||||
case NODE_LVAR:
|
||||
idx = lv_idx(s, nsym(tree));
|
||||
idx = lv_idx(s, node_to_sym(tree));
|
||||
if (idx > 0) {
|
||||
if (idx != sp) {
|
||||
gen_move(s, idx, sp, val);
|
||||
@@ -2950,17 +2951,17 @@ gen_assignment(codegen_scope *s, node *tree, node *rhs, int sp, int val)
|
||||
break;
|
||||
}
|
||||
else { /* upvar */
|
||||
gen_setupvar(s, sp, nsym(tree));
|
||||
gen_setupvar(s, sp, node_to_sym(tree));
|
||||
}
|
||||
break;
|
||||
case NODE_IVAR:
|
||||
gen_setxv(s, OP_SETIV, sp, nsym(tree), val);
|
||||
gen_setxv(s, OP_SETIV, sp, node_to_sym(tree), val);
|
||||
break;
|
||||
case NODE_CVAR:
|
||||
gen_setxv(s, OP_SETCV, sp, nsym(tree), val);
|
||||
gen_setxv(s, OP_SETCV, sp, node_to_sym(tree), val);
|
||||
break;
|
||||
case NODE_CONST:
|
||||
gen_setxv(s, OP_SETCONST, sp, nsym(tree), val);
|
||||
gen_setxv(s, OP_SETCONST, sp, node_to_sym(tree), val);
|
||||
break;
|
||||
case NODE_COLON2:
|
||||
case NODE_COLON3:
|
||||
@@ -2971,12 +2972,12 @@ gen_assignment(codegen_scope *s, node *tree, node *rhs, int sp, int val)
|
||||
push();
|
||||
if (type == NODE_COLON2) {
|
||||
codegen(s, tree->car, VAL);
|
||||
idx = new_sym(s, nsym(tree->cdr));
|
||||
idx = new_sym(s, node_to_sym(tree->cdr));
|
||||
}
|
||||
else { /* NODE_COLON3 */
|
||||
genop_1(s, OP_OCLASS, cursp());
|
||||
push();
|
||||
idx = new_sym(s, nsym(tree));
|
||||
idx = new_sym(s, node_to_sym(tree));
|
||||
}
|
||||
if (rhs) {
|
||||
codegen(s, rhs, VAL); pop();
|
||||
@@ -2990,7 +2991,7 @@ gen_assignment(codegen_scope *s, node *tree, node *rhs, int sp, int val)
|
||||
case NODE_SCALL:
|
||||
{
|
||||
int noself = 0, safe = (type == NODE_SCALL), skip = 0, top, call, n = 0;
|
||||
mrb_sym mid = nsym(tree->cdr->car);
|
||||
mrb_sym mid = node_to_sym(tree->cdr->car);
|
||||
|
||||
top = cursp();
|
||||
if (val || sp == cursp()) {
|
||||
@@ -3168,9 +3169,9 @@ gen_literal_array(codegen_scope *s, node *tree, mrb_bool sym, int val)
|
||||
int i = 0, j = 0, gen = 0;
|
||||
|
||||
while (tree) {
|
||||
switch (nint(tree->car->car)) {
|
||||
switch (node_to_int(tree->car->car)) {
|
||||
case NODE_STR:
|
||||
if ((tree->cdr == NULL) && (nint(tree->car->cdr->cdr) == 0))
|
||||
if ((tree->cdr == NULL) && (node_to_int(tree->car->cdr->cdr) == 0))
|
||||
break;
|
||||
/* fall through */
|
||||
case NODE_STMTS:
|
||||
@@ -3226,7 +3227,7 @@ gen_literal_array(codegen_scope *s, node *tree, mrb_bool sym, int val)
|
||||
}
|
||||
else {
|
||||
while (tree) {
|
||||
switch (nint(tree->car->car)) {
|
||||
switch (node_to_int(tree->car->car)) {
|
||||
case NODE_STMTS: case NODE_BEGIN: case NODE_BLOCK:
|
||||
codegen(s, tree->car, NOVAL);
|
||||
}
|
||||
@@ -3292,7 +3293,7 @@ readint(codegen_scope *s, const char *p, int base, mrb_bool neg, mrb_bool *overf
|
||||
static void
|
||||
gen_retval(codegen_scope *s, node *tree)
|
||||
{
|
||||
if (nint(tree->car) == NODE_SPLAT) {
|
||||
if (node_to_int(tree->car) == NODE_SPLAT) {
|
||||
codegen(s, tree, VAL);
|
||||
pop();
|
||||
genop_1(s, OP_ARYSPLAT, cursp());
|
||||
@@ -3306,7 +3307,7 @@ gen_retval(codegen_scope *s, node *tree)
|
||||
static mrb_bool
|
||||
true_always(node *tree)
|
||||
{
|
||||
switch (nint(tree->car)) {
|
||||
switch (node_to_int(tree->car)) {
|
||||
case NODE_TRUE:
|
||||
case NODE_INT:
|
||||
case NODE_STR:
|
||||
@@ -3320,7 +3321,7 @@ true_always(node *tree)
|
||||
static mrb_bool
|
||||
false_always(node *tree)
|
||||
{
|
||||
switch (nint(tree->car)) {
|
||||
switch (node_to_int(tree->car)) {
|
||||
case NODE_FALSE:
|
||||
case NODE_NIL:
|
||||
return TRUE;
|
||||
@@ -3349,14 +3350,14 @@ gen_blkmove(codegen_scope *s, uint16_t ainfo, int lv)
|
||||
static void
|
||||
codegen_op_asgn(codegen_scope *s, node *tree, int val)
|
||||
{
|
||||
mrb_sym sym = nsym(tree->cdr->car);
|
||||
mrb_sym sym = node_to_sym(tree->cdr->car);
|
||||
mrb_int len;
|
||||
const char *name = mrb_sym_name_len(s->mrb, sym, &len);
|
||||
int idx, callargs = -1, vsp = -1;
|
||||
|
||||
if ((len == 2 && name[0] == '|' && name[1] == '|') &&
|
||||
(nint(tree->car->car) == NODE_CONST ||
|
||||
nint(tree->car->car) == NODE_CVAR)) {
|
||||
(node_to_int(tree->car->car) == NODE_CONST ||
|
||||
node_to_int(tree->car->car) == NODE_CVAR)) {
|
||||
int catch_entry, begin, end;
|
||||
int noexc, exc;
|
||||
struct loopinfo *lp;
|
||||
@@ -3376,7 +3377,7 @@ codegen_op_asgn(codegen_scope *s, node *tree, int val)
|
||||
dispatch(s, noexc);
|
||||
loop_pop(s, NOVAL);
|
||||
}
|
||||
else if (nint(tree->car->car) == NODE_CALL) {
|
||||
else if (node_to_int(tree->car->car) == NODE_CALL) {
|
||||
node *n = tree->car->cdr;
|
||||
int base, i, nargs = 0;
|
||||
callargs = 0;
|
||||
@@ -3386,7 +3387,7 @@ codegen_op_asgn(codegen_scope *s, node *tree, int val)
|
||||
push();
|
||||
}
|
||||
codegen(s, n->car, VAL); /* receiver */
|
||||
idx = new_sym(s, nsym(n->cdr->car));
|
||||
idx = new_sym(s, node_to_sym(n->cdr->car));
|
||||
base = cursp()-1;
|
||||
if (n->cdr->cdr->car) {
|
||||
nargs = gen_values(s, n->cdr->cdr->car->car, VAL, 13);
|
||||
@@ -3431,7 +3432,7 @@ codegen_op_asgn(codegen_scope *s, node *tree, int val)
|
||||
if (val && vsp >= 0) {
|
||||
gen_move(s, vsp, cursp(), 1);
|
||||
}
|
||||
if (nint(tree->car->car) == NODE_CALL) {
|
||||
if (node_to_int(tree->car->car) == NODE_CALL) {
|
||||
if (callargs == CALL_MAXARGS) {
|
||||
pop();
|
||||
genop_2(s, OP_ARYPUSH, cursp(), 1);
|
||||
@@ -3441,7 +3442,7 @@ codegen_op_asgn(codegen_scope *s, node *tree, int val)
|
||||
callargs++;
|
||||
}
|
||||
pop();
|
||||
idx = new_sym(s, attrsym(s, nsym(tree->car->cdr->cdr->car)));
|
||||
idx = new_sym(s, attrsym(s, node_to_sym(tree->car->cdr->cdr->car)));
|
||||
genop_3(s, OP_SEND, cursp(), idx, callargs);
|
||||
}
|
||||
else {
|
||||
@@ -3498,7 +3499,7 @@ codegen_op_asgn(codegen_scope *s, node *tree, int val)
|
||||
callargs++;
|
||||
}
|
||||
pop();
|
||||
idx = new_sym(s, attrsym(s,nsym(tree->car->cdr->cdr->car)));
|
||||
idx = new_sym(s, attrsym(s,node_to_sym(tree->car->cdr->cdr->car)));
|
||||
genop_3(s, OP_SEND, cursp(), idx, callargs);
|
||||
}
|
||||
}
|
||||
@@ -3510,7 +3511,7 @@ codegen_masgn(codegen_scope *s, node *tree, int val)
|
||||
node *t = tree->cdr, *p;
|
||||
int rhs = cursp();
|
||||
|
||||
if (!val && nint(t->car) == NODE_ARRAY && t->cdr && nosplat(t->cdr)) {
|
||||
if (!val && node_to_int(t->car) == NODE_ARRAY && t->cdr && nosplat(t->cdr)) {
|
||||
/* fixed rhs */
|
||||
t = t->cdr;
|
||||
while (t) {
|
||||
@@ -3642,7 +3643,7 @@ codegen_rescue(codegen_scope *s, node *tree, int val)
|
||||
dispatch(s, pos1);
|
||||
pos2 = JMPLINK_START;
|
||||
do {
|
||||
if (n4 && n4->car && nint(n4->car->car) == NODE_SPLAT) {
|
||||
if (n4 && n4->car && node_to_int(n4->car->car) == NODE_SPLAT) {
|
||||
codegen(s, n4->car, VAL);
|
||||
gen_move(s, cursp(), exc, 0);
|
||||
push_n(2); pop_n(2); /* space for one arg and a block */
|
||||
@@ -3704,7 +3705,7 @@ static void
|
||||
codegen_ensure(codegen_scope *s, node *tree, int val)
|
||||
{
|
||||
if (!tree->cdr || !tree->cdr->cdr ||
|
||||
(nint(tree->cdr->cdr->car) == NODE_STMTS &&
|
||||
(node_to_int(tree->cdr->cdr->car) == NODE_STMTS &&
|
||||
tree->cdr->cdr->cdr)) {
|
||||
int catch_entry, begin, end, target;
|
||||
int idx;
|
||||
@@ -3767,9 +3768,9 @@ codegen_if(codegen_scope *s, node *tree, int val)
|
||||
codegen(s, elsepart, val);
|
||||
return;
|
||||
}
|
||||
if (nint(tree->car->car) == NODE_CALL) {
|
||||
if (node_to_int(tree->car->car) == NODE_CALL) {
|
||||
node *n = tree->car->cdr;
|
||||
mrb_sym mid = nsym(n->cdr->car);
|
||||
mrb_sym mid = node_to_sym(n->cdr->car);
|
||||
mrb_sym sym_nil_p = MRB_SYM_Q_2(s->mrb, nil);
|
||||
if (mid == sym_nil_p && n->cdr->cdr->car == NULL) {
|
||||
nil_p = TRUE;
|
||||
@@ -3883,16 +3884,16 @@ codegen_false(codegen_scope *s, node *tree, int val)
|
||||
}
|
||||
|
||||
static void
|
||||
codegen_lvar(codegen_scope *s, node *tree, int val)
|
||||
codegen_lvar(codegen_scope *s, mrb_sym sym, int val)
|
||||
{
|
||||
if (!val) return;
|
||||
int idx = lv_idx(s, nsym(tree));
|
||||
int idx = lv_idx(s, sym);
|
||||
|
||||
if (idx > 0) {
|
||||
gen_move(s, cursp(), idx, val);
|
||||
}
|
||||
else {
|
||||
gen_getupvar(s, cursp(), nsym(tree));
|
||||
gen_getupvar(s, cursp(), sym);
|
||||
}
|
||||
push();
|
||||
}
|
||||
@@ -3901,56 +3902,56 @@ static void
|
||||
codegen_nvar(codegen_scope *s, node *tree, int val)
|
||||
{
|
||||
if (!val) return;
|
||||
int idx = nint(tree);
|
||||
int idx = node_to_int(tree);
|
||||
|
||||
gen_move(s, cursp(), idx, val);
|
||||
push();
|
||||
}
|
||||
|
||||
static void
|
||||
codegen_gvar(codegen_scope *s, node *tree, int val)
|
||||
codegen_gvar(codegen_scope *s, mrb_sym sym, int val)
|
||||
{
|
||||
if (!val) return;
|
||||
int sym = new_sym(s, nsym(tree));
|
||||
int i = new_sym(s, sym);
|
||||
|
||||
genop_2(s, OP_GETGV, cursp(), sym);
|
||||
genop_2(s, OP_GETGV, cursp(), i);
|
||||
push();
|
||||
}
|
||||
|
||||
static void
|
||||
codegen_ivar(codegen_scope *s, node *tree, int val)
|
||||
codegen_ivar(codegen_scope *s, mrb_sym sym, int val)
|
||||
{
|
||||
if (!val) return;
|
||||
int sym = new_sym(s, nsym(tree));
|
||||
int i = new_sym(s, sym);
|
||||
|
||||
genop_2(s, OP_GETIV, cursp(), sym);
|
||||
genop_2(s, OP_GETIV, cursp(), i);
|
||||
push();
|
||||
}
|
||||
|
||||
static void
|
||||
codegen_cvar(codegen_scope *s, node *tree, int val)
|
||||
codegen_cvar(codegen_scope *s, mrb_sym sym, int val)
|
||||
{
|
||||
if (!val) return;
|
||||
int sym = new_sym(s, nsym(tree));
|
||||
int i = new_sym(s, sym);
|
||||
|
||||
genop_2(s, OP_GETCV, cursp(), sym);
|
||||
genop_2(s, OP_GETCV, cursp(), i);
|
||||
push();
|
||||
}
|
||||
|
||||
static void
|
||||
codegen_const(codegen_scope *s, node *tree, int val)
|
||||
codegen_const(codegen_scope *s, mrb_sym sym, int val)
|
||||
{
|
||||
int sym = new_sym(s, nsym(tree));
|
||||
int i = new_sym(s, sym);
|
||||
|
||||
genop_2(s, OP_GETCONST, cursp(), sym);
|
||||
genop_2(s, OP_GETCONST, cursp(), i);
|
||||
if (val) push();
|
||||
}
|
||||
|
||||
static void
|
||||
codegen_sym(codegen_scope *s, node *tree, int val)
|
||||
codegen_sym(codegen_scope *s, mrb_sym sym, int val)
|
||||
{
|
||||
int sym = new_sym(s, nsym(tree));
|
||||
gen_load_op2(s, OP_LOADSYM, sym, val);
|
||||
int i = new_sym(s, sym);
|
||||
gen_load_op2(s, OP_LOADSYM, i, val);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -4053,7 +4054,7 @@ codegen_case(codegen_scope *s, node *tree, int val)
|
||||
if (head) {
|
||||
gen_move(s, cursp(), head, 0);
|
||||
push(); push(); pop(); pop(); pop();
|
||||
if (nint(n->car->car) == NODE_SPLAT) {
|
||||
if (node_to_int(n->car->car) == NODE_SPLAT) {
|
||||
genop_3(s, OP_SEND, cursp(), new_sym(s, MRB_SYM_2(s->mrb, __case_eqq)), 1);
|
||||
}
|
||||
else {
|
||||
@@ -4174,7 +4175,7 @@ codegen_while_until(codegen_scope *s, node *tree, int val, int nt)
|
||||
static void
|
||||
codegen_negate(codegen_scope *s, node *tree, int val)
|
||||
{
|
||||
int nt = nint(tree->car);
|
||||
int nt = node_to_int(tree->car);
|
||||
switch (nt) {
|
||||
#ifndef MRB_NO_FLOAT
|
||||
case NODE_FLOAT:
|
||||
@@ -4192,7 +4193,7 @@ codegen_negate(codegen_scope *s, node *tree, int val)
|
||||
case NODE_INT:
|
||||
if (val) {
|
||||
char *p = (char*)tree->cdr->car;
|
||||
int base = nint(tree->cdr->cdr->car);
|
||||
int base = node_to_int(tree->cdr->cdr->car);
|
||||
mrb_int i;
|
||||
mrb_bool overflow;
|
||||
|
||||
@@ -4238,7 +4239,7 @@ codegen_int(codegen_scope *s, node *tree, int val)
|
||||
{
|
||||
if (!val) return;
|
||||
char *p = (char*)tree->car;
|
||||
int base = nint(tree->cdr->car);
|
||||
int base = node_to_int(tree->cdr->car);
|
||||
mrb_int i;
|
||||
mrb_bool overflow;
|
||||
|
||||
@@ -4257,7 +4258,7 @@ static void
|
||||
codegen_xstr(codegen_scope *s, node *tree, int val)
|
||||
{
|
||||
char *p = (char*)tree->car;
|
||||
mrb_int len = nint(tree->cdr);
|
||||
mrb_int len = node_to_int(tree->cdr);
|
||||
int off = new_lit_str(s, p, len);
|
||||
int sym;
|
||||
|
||||
@@ -4286,7 +4287,7 @@ codegen_dxstr(codegen_scope *s, node *tree, int val)
|
||||
codegen(s, tree->car, VAL);
|
||||
n = tree->cdr;
|
||||
while (n) {
|
||||
if (nint(n->car->car) == NODE_XSTR) {
|
||||
if (node_to_int(n->car->car) == NODE_XSTR) {
|
||||
n->car->car = (struct mrb_ast_node*)(intptr_t)NODE_STR;
|
||||
mrb_assert(!n->cdr); /* must be the end */
|
||||
}
|
||||
@@ -4333,7 +4334,7 @@ codegen_heredoc_dstr(codegen_scope *s, node *tree, int val)
|
||||
node *n = tree;
|
||||
|
||||
while (n) {
|
||||
if (nint(n->car->car) != NODE_STR) {
|
||||
if (node_to_int(n->car->car) != NODE_STR) {
|
||||
codegen(s, n->car, NOVAL);
|
||||
}
|
||||
n = n->cdr;
|
||||
@@ -4346,7 +4347,7 @@ codegen_str(codegen_scope *s, node *tree, int val)
|
||||
{
|
||||
if (val) {
|
||||
char *p = (char*)tree->car;
|
||||
mrb_int len = nint(tree->cdr);
|
||||
mrb_int len = node_to_int(tree->cdr);
|
||||
int off = new_lit_str(s, p, len);
|
||||
|
||||
genop_2(s, OP_STRING, cursp(), off);
|
||||
@@ -4410,7 +4411,7 @@ codegen_dregx(codegen_scope *s, node *tree, int val)
|
||||
node *n = tree->car;
|
||||
|
||||
while (n) {
|
||||
if (nint(n->car->car) != NODE_STR) {
|
||||
if (node_to_int(n->car->car) != NODE_STR) {
|
||||
codegen(s, n->car, NOVAL);
|
||||
}
|
||||
n = n->cdr;
|
||||
@@ -4468,7 +4469,7 @@ codegen_asgn(codegen_scope *s, node *tree, int val)
|
||||
static void
|
||||
codegen_def(codegen_scope *s, node *tree, int val)
|
||||
{
|
||||
int sym = new_sym(s, nsym(tree->car));
|
||||
int sym = new_sym(s, node_to_sym(tree->car));
|
||||
int idx = lambda_body(s, tree->cdr, 0);
|
||||
|
||||
genop_1(s, OP_TCLASS, cursp());
|
||||
@@ -4484,7 +4485,7 @@ static void
|
||||
codegen_sdef(codegen_scope *s, node *tree, int val)
|
||||
{
|
||||
node *recv = tree->car;
|
||||
int sym = new_sym(s, nsym(tree->cdr->car));
|
||||
int sym = new_sym(s, node_to_sym(tree->cdr->car));
|
||||
int idx = lambda_body(s, tree->cdr->cdr, 0);
|
||||
|
||||
codegen(s, recv, VAL);
|
||||
@@ -4528,10 +4529,10 @@ codegen_class(codegen_scope *s, node *tree, int val)
|
||||
push();
|
||||
}
|
||||
pop(); pop();
|
||||
idx = new_sym(s, nsym(tree->car->cdr));
|
||||
idx = new_sym(s, node_to_sym(tree->car->cdr));
|
||||
genop_2(s, OP_CLASS, cursp(), idx);
|
||||
body = tree->cdr->cdr->car;
|
||||
if (nint(body->cdr->car) == NODE_STMTS && body->cdr->cdr == NULL) {
|
||||
if (node_to_int(body->cdr->car) == NODE_STMTS && body->cdr->cdr == NULL) {
|
||||
genop_1(s, OP_LOADNIL, cursp());
|
||||
}
|
||||
else {
|
||||
@@ -4560,9 +4561,9 @@ codegen_module(codegen_scope *s, node *tree, int val)
|
||||
codegen(s, tree->car->car, VAL);
|
||||
}
|
||||
pop();
|
||||
idx = new_sym(s, nsym(tree->car->cdr));
|
||||
idx = new_sym(s, node_to_sym(tree->car->cdr));
|
||||
genop_2(s, OP_MODULE, cursp(), idx);
|
||||
if (nint(tree->cdr->car->cdr->car) == NODE_STMTS &&
|
||||
if (node_to_int(tree->cdr->car->cdr->car) == NODE_STMTS &&
|
||||
tree->cdr->car->cdr->cdr == NULL) {
|
||||
genop_1(s, OP_LOADNIL, cursp());
|
||||
}
|
||||
@@ -4583,7 +4584,7 @@ codegen_sclass(codegen_scope *s, node *tree, int val)
|
||||
codegen(s, tree->car, VAL);
|
||||
pop();
|
||||
genop_1(s, OP_SCLASS, cursp());
|
||||
if (nint(tree->cdr->car->cdr->car) == NODE_STMTS &&
|
||||
if (node_to_int(tree->cdr->car->cdr->car) == NODE_STMTS &&
|
||||
tree->cdr->car->cdr->cdr == NULL) {
|
||||
genop_1(s, OP_LOADNIL, cursp());
|
||||
}
|
||||
@@ -4599,8 +4600,8 @@ codegen_sclass(codegen_scope *s, node *tree, int val)
|
||||
static void
|
||||
codegen_alias(codegen_scope *s, node *tree, int val)
|
||||
{
|
||||
int a = new_sym(s, nsym(tree->car));
|
||||
int b = new_sym(s, nsym(tree->cdr));
|
||||
int a = new_sym(s, node_to_sym(tree->car));
|
||||
int b = new_sym(s, node_to_sym(tree->cdr));
|
||||
|
||||
genop_2(s, OP_ALIAS, a, b);
|
||||
gen_load_nil(s, val);
|
||||
@@ -4612,7 +4613,7 @@ codegen_undef(codegen_scope *s, node *tree, int val)
|
||||
node *t = tree;
|
||||
|
||||
while (t) {
|
||||
int symbol = new_sym(s, nsym(t->car));
|
||||
int symbol = new_sym(s, node_to_sym(t->car));
|
||||
genop_1(s, OP_UNDEF, symbol);
|
||||
t = t->cdr;
|
||||
}
|
||||
@@ -4673,7 +4674,7 @@ codegen_next(codegen_scope *s, node *tree, int val)
|
||||
static void
|
||||
codegen_colon2(codegen_scope *s, node *tree, int val)
|
||||
{
|
||||
int sym = new_sym(s, nsym(tree->cdr));
|
||||
int sym = new_sym(s, node_to_sym(tree->cdr));
|
||||
|
||||
codegen(s, tree->car, VAL);
|
||||
pop();
|
||||
@@ -4684,7 +4685,7 @@ codegen_colon2(codegen_scope *s, node *tree, int val)
|
||||
static void
|
||||
codegen_colon3(codegen_scope *s, node *tree, int val)
|
||||
{
|
||||
int sym = new_sym(s, nsym(tree));
|
||||
int sym = new_sym(s, node_to_sym(tree));
|
||||
|
||||
genop_1(s, OP_OCLASS, cursp());
|
||||
genop_2(s, OP_GETMCNST, cursp(), sym);
|
||||
@@ -4729,7 +4730,7 @@ codegen_retry(codegen_scope *s, node *tree, int val)
|
||||
static void
|
||||
codegen_back_ref(codegen_scope *s, node *tree, int val)
|
||||
{
|
||||
char buf[] = {'$', nchar(tree)};
|
||||
char buf[] = {'$', node_to_char(tree)};
|
||||
int sym = new_sym(s, mrb_intern(s->mrb, buf, sizeof(buf)));
|
||||
gen_load_op2(s, OP_GETGV, sym, val);
|
||||
}
|
||||
@@ -4741,7 +4742,7 @@ codegen_nth_ref(codegen_scope *s, node *tree, int val)
|
||||
mrb_value str;
|
||||
int sym;
|
||||
|
||||
str = mrb_format(mrb, "$%d", nint(tree));
|
||||
str = mrb_format(mrb, "$%d", node_to_int(tree));
|
||||
sym = new_sym(s, mrb_intern_str(mrb, str));
|
||||
gen_load_op2(s, OP_GETGV, sym, val);
|
||||
}
|
||||
@@ -4918,6 +4919,53 @@ codegen_yield(codegen_scope *s, node *tree, int val)
|
||||
}
|
||||
|
||||
|
||||
/* Handle variable-sized node types */
|
||||
static mrb_bool
|
||||
codegen_variable_node(codegen_scope *s, node *varnode, int val)
|
||||
{
|
||||
enum node_type nt = VAR_NODE_TYPE(varnode);
|
||||
|
||||
switch (nt) {
|
||||
case NODE_INT:
|
||||
if (val) {
|
||||
gen_int(s, cursp(), INT_NODE_VALUE(varnode));
|
||||
push();
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
case NODE_STR:
|
||||
if (val) {
|
||||
int off = new_lit_str(s, STR_NODE_PTR(varnode), STR_NODE_LEN(varnode));
|
||||
genop_2(s, OP_STRING, cursp(), off);
|
||||
push();
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
case NODE_SYM:
|
||||
codegen_sym(s, SYM_NODE_VALUE(varnode), val);
|
||||
return TRUE;
|
||||
|
||||
case NODE_LVAR:
|
||||
codegen_lvar(s, VAR_NODE_SYMBOL(varnode), val);
|
||||
return TRUE;
|
||||
|
||||
case NODE_GVAR:
|
||||
codegen_gvar(s, VAR_NODE_SYMBOL(varnode), val);
|
||||
return TRUE;
|
||||
|
||||
case NODE_IVAR:
|
||||
codegen_ivar(s, VAR_NODE_SYMBOL(varnode), val);
|
||||
return TRUE;
|
||||
|
||||
case NODE_CVAR:
|
||||
codegen_cvar(s, VAR_NODE_SYMBOL(varnode), val);
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
return FALSE; /* Not handled, fall through to main codegen */
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
codegen(codegen_scope *s, node *tree, int val)
|
||||
{
|
||||
@@ -4934,6 +4982,9 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
}
|
||||
|
||||
head = (struct mrb_ast_head_node*)tree;
|
||||
nt = node_to_int(tree->car);
|
||||
|
||||
|
||||
s->rlev++;
|
||||
if (s->rlev > MRB_CODEGEN_LEVEL_MAX) {
|
||||
codegen_error(s, "too complex expression");
|
||||
@@ -4951,7 +5002,6 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
s->filename_sym = mrb_parser_get_filename(s->parser, head->filename_index);
|
||||
}
|
||||
|
||||
nt = nint(tree->car);
|
||||
s->lineno = head->lineno;
|
||||
tree = tree->cdr;
|
||||
switch (nt) {
|
||||
@@ -5092,7 +5142,7 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
break;
|
||||
|
||||
case NODE_LVAR:
|
||||
codegen_lvar(s, tree, val);
|
||||
codegen_lvar(s, node_to_sym(tree), val);
|
||||
break;
|
||||
|
||||
case NODE_NVAR:
|
||||
@@ -5100,19 +5150,19 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
break;
|
||||
|
||||
case NODE_GVAR:
|
||||
codegen_gvar(s, tree, val);
|
||||
codegen_gvar(s, node_to_sym(tree), val);
|
||||
break;
|
||||
|
||||
case NODE_IVAR:
|
||||
codegen_ivar(s, tree, val);
|
||||
codegen_ivar(s, node_to_sym(tree), val);
|
||||
break;
|
||||
|
||||
case NODE_CVAR:
|
||||
codegen_cvar(s, tree, val);
|
||||
codegen_cvar(s, node_to_sym(tree), val);
|
||||
break;
|
||||
|
||||
case NODE_CONST:
|
||||
codegen_const(s, tree, val);
|
||||
codegen_const(s, node_to_sym(tree), val);
|
||||
break;
|
||||
|
||||
case NODE_BACK_REF:
|
||||
@@ -5182,7 +5232,7 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
break;
|
||||
|
||||
case NODE_SYM:
|
||||
codegen_sym(s, tree, val);
|
||||
codegen_sym(s, node_to_sym(tree), val);
|
||||
break;
|
||||
|
||||
case NODE_DSYM:
|
||||
@@ -5237,6 +5287,10 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
codegen_postexe(s, tree, val);
|
||||
break;
|
||||
|
||||
case NODE_VARIABLE:
|
||||
codegen_variable_node(s, tree, val);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -100,6 +100,7 @@ enum node_type {
|
||||
NODE_LITERAL_DELIM,
|
||||
NODE_WORDS,
|
||||
NODE_SYMBOLS,
|
||||
NODE_VARIABLE,
|
||||
NODE_LAST
|
||||
};
|
||||
|
||||
@@ -153,4 +154,96 @@ struct mrb_ast_head_node {
|
||||
uint16_t lineno, filename_index;
|
||||
};
|
||||
|
||||
/* Variable-sized AST nodes - Phase 1 Infrastructure */
|
||||
|
||||
/* Variable node header - common to all variable-sized nodes */
|
||||
struct mrb_ast_var_header {
|
||||
uint16_t lineno; /* Line number information */
|
||||
uint16_t filename_index; /* File index information */
|
||||
uint8_t node_type; /* NODE_INT, NODE_STR, NODE_SYM, etc. */
|
||||
uint8_t size_class; /* Size class for allocation/deallocation */
|
||||
uint16_t flags; /* Type-specific flags and metadata */
|
||||
/* Total: 8 bytes header for all variable nodes */
|
||||
};
|
||||
|
||||
/* Size class enumeration */
|
||||
enum mrb_ast_size_class {
|
||||
SIZE_CLASS_TINY = 0, /* 8-16 bytes - symbols, small values */
|
||||
SIZE_CLASS_SMALL = 1, /* 16-32 bytes - most nodes */
|
||||
SIZE_CLASS_MEDIUM = 2, /* 32-64 bytes - complex expressions */
|
||||
SIZE_CLASS_LARGE = 3, /* 64-128 bytes - large arrays/calls */
|
||||
SIZE_CLASS_XLARGE = 4, /* 128+ bytes - very large constructs */
|
||||
SIZE_CLASS_COUNT = 5
|
||||
};
|
||||
|
||||
/* Size class limits for allocation decisions */
|
||||
#define SIZE_CLASS_LIMITS { 16, 32, 64, 128, 256 }
|
||||
|
||||
/* Node type flags */
|
||||
#define VAR_NODE_FLAG_INLINE_DATA 0x0001 /* Data stored inline */
|
||||
#define VAR_NODE_FLAG_HEAP_ALLOCATED 0x0002 /* Large data on heap */
|
||||
#define VAR_NODE_FLAG_CACHED 0x0004 /* Node is cached/reusable */
|
||||
|
||||
/* Phase 1 Variable Node Structures */
|
||||
|
||||
/* Variable-sized symbol node */
|
||||
struct mrb_ast_sym_node {
|
||||
struct mrb_ast_var_header header; /* 8 bytes */
|
||||
mrb_sym symbol; /* Direct symbol reference */
|
||||
/* Total: 12-16 bytes vs previous 20+ bytes + indirection */
|
||||
};
|
||||
|
||||
/* Variable-sized string node with inline storage */
|
||||
struct mrb_ast_str_node {
|
||||
struct mrb_ast_var_header header; /* 8 bytes */
|
||||
size_t len; /* String length */
|
||||
char data[]; /* Flexible array - inline string storage */
|
||||
/* Total: Variable (16 + string_length) vs previous 20+ bytes + separate allocation */
|
||||
};
|
||||
|
||||
/* Variable-sized integer node */
|
||||
struct mrb_ast_int_node {
|
||||
struct mrb_ast_var_header header; /* 8 bytes */
|
||||
int32_t value; /* Direct 32-bit integer storage */
|
||||
};
|
||||
|
||||
/* Variable-sized node for variables (lvar, ivar, etc.) */
|
||||
struct mrb_ast_var_node {
|
||||
struct mrb_ast_var_header header;
|
||||
mrb_sym symbol;
|
||||
};
|
||||
|
||||
/* String storage strategy thresholds */
|
||||
#define STR_INLINE_THRESHOLD 48 /* Inline strings <= 48 bytes */
|
||||
#define STR_SMALL_THRESHOLD 128 /* Small strings <= 128 bytes */
|
||||
|
||||
#define VAR_NODE_TYPE(n) ((enum node_type)(((struct mrb_ast_var_header*)(n))->node_type))
|
||||
#define VAR_NODE_CLASS(n) (((struct mrb_ast_var_header*)(n))->size_class)
|
||||
|
||||
/* Type-safe casting macros */
|
||||
#define var_header(n) ((struct mrb_ast_var_header*)(n))
|
||||
|
||||
/* Common type casting macros used by parser and codegen */
|
||||
#define node_to_sym(x) ((mrb_sym)(intptr_t)(x))
|
||||
#define sym_to_node(x) ((node*)(intptr_t)(x))
|
||||
#define int_to_node(x) ((node*)(intptr_t)(x))
|
||||
#define head(x) ((struct mrb_ast_head_node*)(x))
|
||||
#define node_to_int(x) ((int)(intptr_t)(x))
|
||||
#define node_to_type(x) ((enum node_type)(intptr_t)(x))
|
||||
#define node_to_char(x) ((char)(intptr_t)(x))
|
||||
|
||||
/* Phase 1 node casting macros */
|
||||
#define sym_node(n) ((struct mrb_ast_sym_node*)(n))
|
||||
#define str_node(n) ((struct mrb_ast_str_node*)(n))
|
||||
#define int_node(n) ((struct mrb_ast_int_node*)(n))
|
||||
#define var_node(n) ((struct mrb_ast_var_node*)(n))
|
||||
|
||||
/* Phase 1 value access macros */
|
||||
#define SYM_NODE_VALUE(n) (sym_node(n)->symbol)
|
||||
#define STR_NODE_PTR(n) (str_node(n)->data)
|
||||
#define STR_NODE_LEN(n) (str_node(n)->len)
|
||||
#define STR_NODE_INLINE_P(n) (var_header(n)->flags & VAR_NODE_FLAG_INLINE_DATA)
|
||||
#define INT_NODE_VALUE(n) (int_node(n)->value)
|
||||
#define VAR_NODE_SYMBOL(n) (var_node(n)->symbol)
|
||||
|
||||
#endif /* MRUBY_COMPILER_NODE_H */
|
||||
|
||||
+353
-148
File diff suppressed because it is too large
Load Diff
+1849
-1644
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user