mruby-compiler: simplify mrb_ast_hash_node from flat array to cons list

Following the same pattern as the case node upgrade (e0f07c9), this
change eliminates the complex flat array packing approach for hash nodes
in favor of simple cons-list storage. The flat array packing provided
no memory benefit since cons lists aren't recycled, while adding
unnecessary complexity to both allocation and traversal logic.

Changes:
- Simplified mrb_ast_hash_node structure from variable-sized flexible
  array to fixed-size structure with cons-list pointer
- Reduced new_hash() from complex 30+ line allocation to simple 4-line
  pattern matching array node implementation
- Updated gen_hash_var() to use cons-list iteration instead of
  interleaved array access (pairs[i*2] for key, pairs[i*2+1] for value)
- Removed HASH_NODE_LEN macro as length tracking is no longer needed
- Maintains identical functionality while reducing code complexity

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Yukihiro "Matz" Matsumoto
2025-09-22 02:32:00 +09:00
parent f50936e8bd
commit f0395a1cf7
4 changed files with 1157 additions and 1214 deletions
+11 -8
View File
@@ -3187,25 +3187,26 @@ static void
gen_hash_var(codegen_scope *s, node *varnode, int val)
{
struct mrb_ast_hash_node *hash = hash_node(varnode);
int len = hash->len;
struct mrb_ast_node **pairs = hash->pairs;
int i;
node *pairs = HASH_NODE_PAIRS(hash);
int regular_pairs = 0;
mrb_bool update = FALSE;
mrb_bool first = TRUE;
if (!val) return;
if (len == 0) {
if (!pairs) {
genop_2(s, OP_HASH, cursp(), 0);
push();
return;
}
/* Process each key-value pair, handling double-splat (**) cases */
for (i = 0; i < len; i++) {
struct mrb_ast_node *key = pairs[i * 2];
struct mrb_ast_node *value = pairs[i * 2 + 1];
/* Process each key-value pair using cons-list iteration, handling double-splat (**) cases */
node *current = pairs;
while (current) {
/* Each current->car is a cons (key . value) */
node *pair = current->car;
struct mrb_ast_node *key = pair->car;
struct mrb_ast_node *value = pair->cdr;
/* Check if this is a double-splat (**kwargs) */
if (node_to_sym(key) == MRB_OPSYM_2(s->mrb, pow)) {
@@ -3249,6 +3250,8 @@ gen_hash_var(codegen_scope *s, node *varnode, int val)
regular_pairs++;
}
first = FALSE;
current = current->cdr;
}
/* Handle any remaining regular pairs */
+3 -7
View File
@@ -225,13 +225,10 @@ struct mrb_ast_array_node {
struct mrb_ast_node *elements; /* Original elements list */
};
/* Variable-sized hash node with inline key-value storage */
/* Variable-sized hash node - revert to original cons list approach */
struct mrb_ast_hash_node {
struct mrb_ast_var_header header; /* 8 bytes */
uint16_t len; /* Number of key-value pairs */
uint16_t flags; /* Hash-specific flags */
/* Interleaved key-value pairs: key0, value0, key1, value1, ... */
struct mrb_ast_node *pairs[]; /* Flexible array for key-value pairs */
struct mrb_ast_var_header header; /* 8 bytes */
struct mrb_ast_node *pairs; /* Original pairs list */
};
/* Phase 3 Variable Node Structures - Control Flow */
@@ -447,7 +444,6 @@ struct mrb_ast_super_node {
#define ARRAY_NODE_ELEMENTS(n) (array_node(n)->elements)
#define HASH_NODE_LEN(n) (hash_node(n)->len)
#define HASH_NODE_PAIRS(n) (hash_node(n)->pairs)
/* Phase 3 value access macros */
+3 -31
View File
@@ -1015,38 +1015,10 @@ new_splat(parser_state *p, node *a)
static node*
new_hash(parser_state *p, node *a)
{
/* Count hash key-value pairs */
uint16_t len = 0;
node *pair_iter = a;
while (pair_iter) {
len++;
pair_iter = pair_iter->cdr;
}
struct mrb_ast_hash_node *n = (struct mrb_ast_hash_node*)parser_alloc_var(p, sizeof(struct mrb_ast_hash_node), SIZE_CLASS_MEDIUM);
/* Calculate total size needed */
size_t base_size = sizeof(struct mrb_ast_hash_node);
size_t pairs_size = len * 2 * sizeof(struct mrb_ast_node*); /* key and value for each pair */
size_t total_size = base_size + pairs_size;
enum mrb_ast_size_class size_class = size_to_class(total_size);
struct mrb_ast_hash_node *n = (struct mrb_ast_hash_node*)parser_alloc_var(p, total_size, size_class);
init_var_header(&n->header, p, NODE_HASH, size_class);
n->len = len;
n->flags = 0;
/* Copy key-value pairs into flexible array */
pair_iter = a;
for (int i = 0; i < len; i++) {
if (pair_iter && pair_iter->car) {
/* Each pair is a cons (key . value) */
node *pair = pair_iter->car;
n->pairs[i * 2] = pair->car; /* key */
n->pairs[i * 2 + 1] = pair->cdr; /* value */
}
pair_iter = pair_iter->cdr;
}
init_var_header(&n->header, p, NODE_HASH, SIZE_CLASS_MEDIUM);
n->pairs = a;
return cons_head((node*)NODE_VARIABLE, (node*)n);
}
File diff suppressed because it is too large Load Diff