mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
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:
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
+1140
-1168
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user