]> git.kaiwu.me - njs.git/commitdiff
Parser: use compact active labels
authorDmitry Volyntsev <xeioex@nginx.com>
Thu, 3 Sep 2026 00:39:41 +0000 (17:39 -0700)
committerDmitry Volyntsev <xeioexception@gmail.com>
Thu, 10 Sep 2026 03:11:04 +0000 (20:11 -0700)
src/njs_parser.c
src/njs_parser.h
src/njs_variable.c
src/njs_variable.h

index a278824b5729bef2559427a2e3acfa47fd685548..0a4419a451d620c924aa48312e3b3698d303afb7 100644 (file)
@@ -549,6 +549,8 @@ njs_parser_init(njs_vm_t *vm, njs_parser_t *parser, njs_parser_scope_t *scope,
     lexer = &parser->lexer0;
     parser->lexer = lexer;
 
+    njs_rbtree_init(&parser->labels, njs_parser_scope_rbtree_compare);
+
     return njs_lexer_init(vm, lexer, file, start, end);
 }
 
@@ -672,7 +674,6 @@ njs_parser_scope_begin(njs_parser_t *parser, njs_scope_t type,
     scope->type = type;
 
     njs_rbtree_init(&scope->variables, njs_parser_scope_rbtree_compare);
-    njs_rbtree_init(&scope->labels, njs_parser_scope_rbtree_compare);
     njs_rbtree_init(&scope->references, njs_parser_scope_rbtree_compare);
 
     parent = parser->scope;
@@ -6036,8 +6037,7 @@ njs_parser_break_continue(njs_parser_t *parser, njs_lexer_token_t *token,
                 return njs_parser_stack_pop(parser);
             }
 
-            if (njs_label_find(parser->vm, parser->scope, token->atom_id)
-                == NULL)
+            if (!njs_label_find(parser, token->atom_id))
             {
                 njs_parser_syntax_error(parser, "Undefined label \"%V\"",
                                         &token->text);
@@ -6445,19 +6445,16 @@ njs_parser_labelled_statement(njs_parser_t *parser, njs_lexer_token_t *token,
     njs_queue_link_t *current)
 {
     uintptr_t       atom_id;
-    njs_variable_t  *label;
 
     atom_id = token->atom_id;
 
-    label = njs_label_find(parser->vm, parser->scope, atom_id);
-    if (label != NULL) {
+    if (njs_label_find(parser, atom_id)) {
         njs_parser_syntax_error(parser, "Label \"%V\" "
                                 "has already been declared", &token->text);
         return NJS_DONE;
     }
 
-    label = njs_label_add(parser->vm, parser->scope, atom_id);
-    if (label == NULL) {
+    if (njs_label_add(parser, atom_id) != NJS_OK) {
         return NJS_ERROR;
     }
 
@@ -6514,7 +6511,7 @@ njs_parser_labelled_statement_after(njs_parser_t *parser,
         return NJS_ERROR;
     }
 
-    ret = njs_label_remove(parser->vm, parser->scope, atom_id);
+    ret = njs_label_remove(parser, atom_id);
     if (ret != NJS_OK) {
         return NJS_ERROR;
     }
@@ -6917,7 +6914,7 @@ njs_parser_function_declaration_after(njs_parser_t *parser,
     njs_value_null_set(&parser->node->u.value);
 
     ret = njs_parser_variable_reference(parser, parser->scope, parser->node,
-                                        atom_id, NJS_DECLARATION);
+                                        atom_id);
     if (ret != NJS_OK) {
         return NJS_ERROR;
     }
@@ -6994,8 +6991,7 @@ njs_parser_function_expression(njs_parser_t *parser, njs_lexer_token_t *token,
     var->self = 1;
 
     ret = njs_parser_variable_reference(parser, parser->scope,
-                                        parser->node->left, atom_id,
-                                        NJS_DECLARATION);
+                                        parser->node->left, atom_id);
     if (ret != NJS_OK) {
         return NJS_ERROR;
     }
@@ -7224,7 +7220,7 @@ njs_parser_arrow_function(njs_parser_t *parser, njs_lexer_token_t *token,
     }
 
     ret = njs_parser_variable_reference(parser, parser->scope, node->left,
-                                        NJS_ATOM_STRING_empty, NJS_DECLARATION);
+                                        NJS_ATOM_STRING_empty);
     if (ret != NJS_OK) {
         return NJS_ERROR;
     }
@@ -8113,8 +8109,7 @@ njs_parser_variable_node(njs_parser_t *parser, uintptr_t atom_id,
         return NULL;
     }
 
-    ret = njs_parser_variable_reference(parser, parser->scope, node, atom_id,
-                                        NJS_DECLARATION);
+    ret = njs_parser_variable_reference(parser, parser->scope, node, atom_id);
     if (njs_slow_path(ret != NJS_OK)) {
         return NULL;
     }
@@ -8171,7 +8166,7 @@ njs_parser_reference(njs_parser_t *parser, njs_lexer_token_t *token)
         node->token_line = token->line;
 
         ret = njs_parser_variable_reference(parser, parser->scope, node,
-                                            token->atom_id, NJS_REFERENCE);
+                                            token->atom_id);
         if (njs_slow_path(ret != NJS_OK)) {
             return NULL;
         }
@@ -8196,7 +8191,7 @@ njs_parser_reference(njs_parser_t *parser, njs_lexer_token_t *token)
         node->token_line = token->line;
 
         ret = njs_parser_variable_reference(parser, parser->scope, node,
-                                            token->atom_id, NJS_REFERENCE);
+                                            token->atom_id);
         if (njs_slow_path(ret != NJS_OK)) {
             return NULL;
         }
@@ -8224,7 +8219,7 @@ njs_parser_reference(njs_parser_t *parser, njs_lexer_token_t *token)
             node->token_line = token->line;
 
             ret = njs_parser_variable_reference(parser, parser->scope, node,
-                                               token->atom_id, NJS_REFERENCE);
+                                                token->atom_id);
             if (njs_slow_path(ret != NJS_OK)) {
                 return NULL;
             }
@@ -8973,7 +8968,7 @@ njs_parser_has_side_effect(njs_parser_node_t *node)
 
 njs_int_t
 njs_parser_variable_reference(njs_parser_t *parser, njs_parser_scope_t *scope,
-    njs_parser_node_t *node, uintptr_t atom_id, njs_reference_type_t type)
+    njs_parser_node_t *node, uintptr_t atom_id)
 {
     njs_rbtree_node_t         *rb_node;
     njs_variable_reference_t  *vr;
index da52dfb2717958c8b50171647d5501b32e1c5104..941a0a10fe431267d74157ff98add6ebf2257bc7 100644 (file)
@@ -14,7 +14,6 @@ struct njs_parser_scope_s {
 
     njs_parser_scope_t              *parent;
     njs_rbtree_t                    variables;
-    njs_rbtree_t                    labels;
     njs_rbtree_t                    references;
 
     njs_arr_t                       *closures;
@@ -35,6 +34,14 @@ typedef struct {
 } njs_parser_array_item_t;
 
 
+typedef struct njs_parser_label_s  njs_parser_label_t;
+
+struct njs_parser_label_s {
+    NJS_RBTREE_NODE                 (node);
+    uintptr_t                       key;
+};
+
+
 struct njs_parser_node_s {
     njs_token_type_t                token_type:16;
     uint8_t                         ctor:1;
@@ -87,6 +94,7 @@ struct njs_parser_s {
     njs_parser_node_t               *node;
     njs_parser_node_t               *target;
     njs_parser_scope_t              *scope;
+    njs_rbtree_t                    labels;
     njs_variable_type_t             var_type;
     njs_int_t                       ret;
 
@@ -145,8 +153,7 @@ njs_variable_t *njs_variable_resolve(njs_vm_t *vm, njs_parser_node_t *node);
 njs_index_t njs_variable_index(njs_vm_t *vm, njs_parser_node_t *node);
 njs_bool_t njs_parser_has_side_effect(njs_parser_node_t *node);
 njs_int_t njs_parser_variable_reference(njs_parser_t *parser,
-    njs_parser_scope_t *scope, njs_parser_node_t *node, uintptr_t atom_id,
-    njs_reference_type_t type);
+    njs_parser_scope_t *scope, njs_parser_node_t *node, uintptr_t atom_id);
 njs_token_type_t njs_parser_unexpected_token(njs_vm_t *vm, njs_parser_t *parser,
     njs_str_t *name, njs_token_type_t type);
 njs_int_t njs_parser_string_create(njs_vm_t *vm, njs_lexer_token_t *token,
index 50b139507ebdd02a07a1686fe12d37e904ea4fd4..47ee500948a5ea01bfc8eb03e199c8de4e7b2d47 100644 (file)
@@ -301,59 +301,41 @@ memory_error:
 }
 
 
-njs_variable_t *
-njs_label_add(njs_vm_t *vm, njs_parser_scope_t *scope, uintptr_t atom_id)
+njs_int_t
+njs_label_add(njs_parser_t *parser, uintptr_t atom_id)
 {
-    njs_variable_t       *label;
-    njs_rbtree_node_t    *node;
-    njs_variable_node_t  var_node, *var_node_new;
-
-    var_node.key = atom_id;
-
-    node = njs_rbtree_find(&scope->labels, &var_node.node);
-
-    if (node != NULL) {
-        return ((njs_variable_node_t *) node)->variable;
-    }
+    njs_parser_label_t  *label;
 
-    label = njs_variable_alloc(vm, atom_id, NJS_VARIABLE_CONST);
+    label = njs_mp_alloc(parser->vm->mem_pool, sizeof(njs_parser_label_t));
     if (njs_slow_path(label == NULL)) {
-        goto memory_error;
-    }
-
-    var_node_new = njs_variable_node_alloc(vm, label, atom_id);
-    if (njs_slow_path(var_node_new == NULL)) {
-        goto memory_error;
+        njs_memory_error(parser->vm);
+        return NJS_ERROR;
     }
 
-    njs_rbtree_insert(&scope->labels, &var_node_new->node);
-
-    return label;
+    label->key = atom_id;
 
-memory_error:
-
-    njs_memory_error(vm);
+    njs_rbtree_insert(&parser->labels, &label->node);
 
-    return NULL;
+    return NJS_OK;
 }
 
 
 njs_int_t
-njs_label_remove(njs_vm_t *vm, njs_parser_scope_t *scope, uintptr_t atom_id)
+njs_label_remove(njs_parser_t *parser, uintptr_t atom_id)
 {
-    njs_rbtree_node_t    *node;
-    njs_variable_node_t  var_node;
+    njs_rbtree_node_t   *node;
+    njs_parser_label_t  label;
 
-    var_node.key = atom_id;
+    label.key = atom_id;
 
-    node = njs_rbtree_find(&scope->labels, &var_node.node);
+    node = njs_rbtree_find(&parser->labels, &label.node);
     if (njs_slow_path(node == NULL)) {
-        njs_internal_error(vm, "failed to find label while removing");
+        njs_internal_error(parser->vm, "failed to find label while removing");
         return NJS_ERROR;
     }
 
-    njs_rbtree_delete(&scope->labels, (njs_rbtree_part_t *) node);
-    njs_variable_node_free(vm, (njs_variable_node_t *) node);
+    njs_rbtree_delete(&parser->labels, (njs_rbtree_part_t *) node);
+    njs_mp_free(parser->vm->mem_pool, node);
 
     return NJS_OK;
 }
@@ -554,26 +536,14 @@ njs_variable_reference(njs_vm_t *vm, njs_parser_node_t *node)
 }
 
 
-njs_variable_t *
-njs_label_find(njs_vm_t *vm, njs_parser_scope_t *scope, uintptr_t atom_id)
+njs_bool_t
+njs_label_find(njs_parser_t *parser, uintptr_t atom_id)
 {
-    njs_rbtree_node_t    *node;
-    njs_variable_node_t  var_node;
-
-    var_node.key = atom_id;
-
-    do {
-        node = njs_rbtree_find(&scope->labels, &var_node.node);
-
-        if (node != NULL) {
-            return ((njs_variable_node_t *) node)->variable;
-        }
+    njs_parser_label_t  label;
 
-        scope = scope->parent;
+    label.key = atom_id;
 
-    } while (scope != NULL);
-
-    return NULL;
+    return njs_rbtree_find(&parser->labels, &label.node) != NULL;
 }
 
 
index be1eec68eb9b734c9b70fa0e7bdb71c6066e39d6..980782baee0ff73c1df0ed6b9a4d899dd867d369 100644 (file)
@@ -59,12 +59,9 @@ njs_variable_t *njs_variable_add(njs_parser_t *parser,
     njs_parser_scope_t *scope, uintptr_t atom_id, njs_variable_type_t type);
 njs_variable_t *njs_variable_function_add(njs_parser_t *parser,
     njs_parser_scope_t *scope, uintptr_t atom_id);
-njs_variable_t * njs_label_add(njs_vm_t *vm, njs_parser_scope_t *scope,
-    uintptr_t atom_id);
-njs_variable_t *njs_label_find(njs_vm_t *vm, njs_parser_scope_t *scope,
-    uintptr_t atom_id);
-njs_int_t njs_label_remove(njs_vm_t *vm, njs_parser_scope_t *scope,
-    uintptr_t atom_id);
+njs_int_t njs_label_add(njs_parser_t *parser, uintptr_t atom_id);
+njs_bool_t njs_label_find(njs_parser_t *parser, uintptr_t atom_id);
+njs_int_t njs_label_remove(njs_parser_t *parser, uintptr_t atom_id);
 njs_variable_t *njs_variable_reference(njs_vm_t *vm, njs_parser_node_t *node);
 njs_variable_t *njs_variable_scope_add(njs_parser_t *parser,
     njs_parser_scope_t *scope, njs_parser_scope_t *original,