js: fix 'teq' for 'js object' which is a return value of an function call(), master
authoryu.dongliang <18588496441@163.com>
Wed, 5 Nov 2025 06:39:21 +0000 (14:39 +0800)
committeryu.dongliang <18588496441@163.com>
Wed, 5 Nov 2025 06:39:30 +0000 (14:39 +0800)
for source code as 'if (obj)', 'if (!obj)', or 'if (Boolean(0))', etc.

16 files changed:
examples/js.html
html/Makefile
js/core/scf_dag.c
js/core/scf_operator_dag.c
js/core/scf_optimizer.c
js/core/scf_optimizer_auto_gc.c
js/core/scf_optimizer_auto_gc_find.c
js/core/scf_optimizer_inline.c
js/core/scf_optimizer_js_teq.c [new file with mode: 0644]
js/core/scf_optimizer_split_call.c
js/core/scf_variable.c
js/core/scf_variable.h
js/doc.c
js/parse/scf_dfa_var.c
js/parse/scf_parse.c
ui/Makefile

index be3e6578e112dbed90ebe7f0be19728c3f85abb6..322c052169551d34b1e52016ab80a614018760f2 100644 (file)
@@ -8,13 +8,7 @@
 
 <script>
 
-var s0 = "123";
-var s1 = "124";
-
-document.write(s0 == s1);
-document.write("<br>");
-
-if (s0 == s1)
+if (Boolean(0))
        document.write(true);
 else
        document.write(false);
index 71e93d11cae8988761fec4d96d200d14eb186ae4..3890934bbc70e116434db7536879129ed811fed0 100644 (file)
@@ -108,6 +108,7 @@ CFILES += ../js/core/scf_optimizer_dag.c
 CFILES += ../js/core/scf_optimizer_inline.c
 
 CFILES += ../js/core/scf_optimizer_js_array.c
+CFILES += ../js/core/scf_optimizer_js_teq.c
 CFILES += ../js/core/scf_optimizer_js_call.c
 
 CFILES += ../js/core/scf_optimizer_split_call.c
index 9fa2005322c5b3c9ed53a48904c0b59da5d94975..54a58cb8d225ea603d40a6b83053a863820961ef 100644 (file)
@@ -583,6 +583,7 @@ int scf_dag_node_same(scf_dag_node_t* dn, const scf_node_t* node)
        if (!dn->childs) {
                if (SCF_OP_CALL == node->type /*&& 1 == node->nb_nodes*/) {
                        int ret = __dn_same_call(dn, node, split);
+                       scf_logd("ret: %d\n", ret);
                        return ret;
                }
 
@@ -638,8 +639,15 @@ int scf_dag_node_same(scf_dag_node_t* dn, const scf_node_t* node)
                }
        }
 
-       if (dn->childs->size != node->nb_nodes)
+       if (dn->childs->size != node->nb_nodes) {
+               if (SCF_OP_CALL == node->type /*&& 1 == node->nb_nodes*/) {
+                       int ret = __dn_same_call(dn, node, split);
+                       scf_logd("ret: %d\n", ret);
+                       return ret;
+               }
+
                return 0;
+       }
 
 cmp_childs:
        for (i = 0; i < node->nb_nodes; i++) {
@@ -687,6 +695,7 @@ cmp_childs:
 
        if (SCF_OP_CALL == dn->type) {
                int ret = __dn_same_call(dn, node, split);
+               scf_logd("ret: %d\n", ret);
                return ret;
        }
 
@@ -724,7 +733,6 @@ int scf_dag_get_node(scf_list_t* h, const scf_node_t* node, scf_dag_node_t** pp)
                node2 = node;
 
        v  = _scf_operand_get((scf_node_t*)node2);
-
        dn = scf_dag_find_node(h, node2);
 
        if (!dn) {
index cac9df1220fe7d3ccb8685e33302aa9f1f9fb35a..103592eda19c49d0dd5b8022a7470f1edaaea4fe 100644 (file)
@@ -373,6 +373,7 @@ static int _scf_dag_op_##name(scf_list_t* h, scf_dag_node_t* parent, scf_dag_nod
 }
 
 SCF_OP_CMP(eq, ==, SCF_OP_EQ)
+SCF_OP_CMP(ne, ==, SCF_OP_NE)
 SCF_OP_CMP(gt, >, SCF_OP_GT)
 SCF_OP_CMP(lt, <, SCF_OP_LT)
 
@@ -406,6 +407,7 @@ scf_dag_operator_t  dag_operators[] =
        {SCF_OP_BIT_OR,         SCF_OP_ASSOCIATIVITY_LEFT, _scf_dag_op_or},
 
        {SCF_OP_EQ,             SCF_OP_ASSOCIATIVITY_LEFT, _scf_dag_op_eq},
+       {SCF_OP_NE,             SCF_OP_ASSOCIATIVITY_LEFT, _scf_dag_op_ne},
        {SCF_OP_GT,             SCF_OP_ASSOCIATIVITY_LEFT, _scf_dag_op_gt},
        {SCF_OP_LT,             SCF_OP_ASSOCIATIVITY_LEFT, _scf_dag_op_lt},
 
index 9cc3516ce52672441e4bfcfa3f375bda7c710cc8..bf449f58b768149de57741a96d3b901f51bd287b 100644 (file)
@@ -2,6 +2,7 @@
 
 extern scf_optimizer_t   scf_optimizer_inline;
 extern scf_optimizer_t   scf_optimizer_js_array;
+extern scf_optimizer_t   scf_optimizer_js_teq;
 extern scf_optimizer_t   scf_optimizer_js_call;
 
 extern scf_optimizer_t   scf_optimizer_split_call;
@@ -36,6 +37,7 @@ static scf_optimizer_t*  scf_optimizers[] =
 {
        &scf_optimizer_inline, // global optimizer
        &scf_optimizer_js_array,
+       &scf_optimizer_js_teq,
        &scf_optimizer_js_call,
 
        &scf_optimizer_split_call,
index bdc2a9349c2ef6905058e4cca090a8649e6e6bc7..afd61f2aa0e59a144264200f00091fbf784405b7 100644 (file)
@@ -439,9 +439,9 @@ static int _auto_gc_last_free(scf_ast_t* ast, scf_function_t* f)
                dn = ds->dag_node;
                v  = dn->var;
 
-               scf_logw("%s(), last free: v_%d_%d/%s, ds->ret_flag: %u\n",
-                               f->node.w->text->data, v->w->line, v->w->pos, v->w->text->data, ds->ret_flag);
-               scf_dn_status_print(ds);
+//             scf_logw("%s(), last free: v_%d_%d/%s, ds->ret_flag: %u\n",
+//                             f->node.w->text->data, v->w->line, v->w->pos, v->w->text->data, ds->ret_flag);
+//             scf_dn_status_print(ds);
 
                if (ds->ret_flag)
                        continue;
index 2c5cf6693c3af2cbf92fccb8cac1c0360ea35452..53dc6a72fba7b64e0f28f0ffd6d2de94f25d4e8f 100644 (file)
@@ -808,7 +808,7 @@ static int _auto_gc_function_find(scf_ast_t* ast, scf_function_t* f, scf_list_t*
        int count = 0;
        int ret;
 
-       scf_logw("--- %s() ---\n", f->node.w->text->data);
+       scf_logd("--- %s() ---\n", f->node.w->text->data);
 
        do {
                for (l = scf_list_head(bb_list_head); l != scf_list_sentinel(bb_list_head); ) {
@@ -848,7 +848,7 @@ static int _auto_gc_function_find(scf_ast_t* ast, scf_function_t* f, scf_list_t*
 
                if (!ds->ret_flag)
                        continue;
-#if 1
+#if 0
                scf_logi("ds: %#lx, ds->ret_flag: %u, ds->ret_index: %d, ds->dag_node->var->arg_flag: %u\n",
                                0xffff & (uintptr_t)ds, ds->ret_flag, ds->ret_index, ds->dag_node->var->arg_flag);
                scf_dn_status_print(ds);
@@ -864,7 +864,7 @@ static int _auto_gc_function_find(scf_ast_t* ast, scf_function_t* f, scf_list_t*
                        _bb_find_ds_alias_leak(ds, c, bb, bb_list_head);
                }
        }
-       scf_logi("--- %s() ---\n\n", f->node.w->text->data);
+       scf_logd("--- %s() ---\n\n", f->node.w->text->data);
 
        return total;
 }
@@ -913,7 +913,7 @@ static int _optimize_auto_gc_find(scf_ast_t* ast, scf_function_t* f, scf_vector_
                        total1 += ret;
                }
 
-               scf_logi("total0: %d, total1: %d\n", total0, total1);
+               scf_logd("total0: %d, total1: %d\n", total0, total1);
 
        } while (total0 != total1);
 
index f7105787b59f944a56d0ea6aad87fb63a2d19ff4..6900ea9143ddca4243a752f6741e00534b055eb0 100644 (file)
@@ -453,8 +453,12 @@ static int _optimize_inline(scf_ast_t* ast, scf_function_t* f, scf_vector_t* fun
 
        int i;
        for (i = 0; i < functions->size; i++) {
+               f  =        functions->data[i];
 
-               int ret = _optimize_inline2(ast, functions->data[i]);
+               if (f->js_flag)
+                       continue;
+
+               int ret = _optimize_inline2(ast, f);
                if (ret < 0) {
                        scf_loge("\n");
                        return ret;
diff --git a/js/core/scf_optimizer_js_teq.c b/js/core/scf_optimizer_js_teq.c
new file mode 100644 (file)
index 0000000..2d64d15
--- /dev/null
@@ -0,0 +1,176 @@
+#include"scf_optimizer.h"
+#include"scf_pointer_alias.h"
+
+static int __js_teq(scf_ast_t* ast, scf_3ac_code_t** pc, scf_node_t* node)
+{
+       scf_3ac_code_t*  c;
+       scf_variable_t*  v;
+       scf_function_t*  f = NULL;
+       scf_type_t*      t = NULL;
+       scf_node_t*      pf;
+       scf_node_t*      fret;
+
+       int ret = scf_ast_find_global_function(&f, ast, "Object_teq");
+       if (ret < 0)
+               return ret;
+
+       ret = scf_ast_find_type_type(&t, ast, SCF_FUNCTION_PTR);
+       if (ret < 0)
+               return ret;
+
+       v = SCF_VAR_ALLOC_BY_TYPE(f->node.w, t, 1, 1, f);
+       if (!v)
+               return -ENOMEM;
+       v->const_literal_flag = 1;
+
+       pf = scf_node_alloc(NULL, v->type, v);
+       scf_variable_free(v);
+       v = NULL;
+       if (!pf)
+               return -ENOMEM;
+
+       ret = scf_ast_find_type_type(&t, ast, SCF_VAR_BOOL);
+       if (ret < 0)
+               return ret;
+
+       v = SCF_VAR_ALLOC_BY_TYPE(f->node.w, t, 0, 0, NULL);
+       if (!v)
+               return -ENOMEM;
+       v->tmp_flag = 1;
+
+       fret = scf_node_alloc(f->node.w, SCF_OP_CALL, NULL);
+       if (!fret) {
+               scf_variable_free(v);
+               scf_node_free(pf);
+               return -ENOMEM;
+       }
+       fret->op     = scf_find_base_operator_by_type(SCF_OP_CALL);
+       fret->result = v;
+       v = NULL;
+
+       scf_node_t* srcs[] = {pf, node};
+
+       c = scf_3ac_code_NN(SCF_OP_CALL, &fret, 1, srcs, 2);
+       if (!c) {
+               scf_node_free(pf);
+               scf_node_free(fret);
+               return -ENOMEM;
+       }
+
+       *pc = c;
+       return 0;
+}
+
+static int _optimize_js_teq_bb(scf_ast_t* ast, scf_function_t* f, scf_basic_block_t* bb, scf_list_t* bb_list_head)
+{
+       scf_3ac_operand_t* src;
+       scf_3ac_operand_t* dst;
+       scf_3ac_code_t*    c;
+       scf_3ac_code_t*    c2;
+       scf_variable_t*    v;
+       scf_node_t*        node;
+       scf_type_t*        Object = NULL;
+       scf_list_t*        l;
+
+       int ret = scf_ast_find_global_type(&Object, ast, "Object");
+       if (ret < 0)
+               return ret;
+
+       for (l = scf_list_head(&bb->code_list_head); l != scf_list_sentinel(&bb->code_list_head); ) {
+
+               c  = scf_list_data(l, scf_3ac_code_t, list);
+               l  = scf_list_next(l);
+
+               if (SCF_OP_3AC_TEQ == c->op->type) {
+                       src  = c->srcs->data[0];
+                       node = src->node;
+
+                       while (SCF_OP_EXPR == node->type)
+                               node = node->nodes[0];
+
+                       v = _scf_operand_get(node);
+
+                       if (v->type != Object->type)
+                               continue;
+
+                       if (SCF_OP_CALL == node->type) {
+                               assert(node->nb_nodes > 0);
+
+                               scf_variable_t* v2 = _scf_operand_get(node->nodes[0]);
+                               scf_function_t* f2 = v2->func_ptr;
+
+                               if (!strcmp(f2->node.w->text->data, "scf__auto_malloc"))
+                                       continue;
+                               scf_logd("f2: %s()\n", f2->node.w->text->data);
+                       }
+
+                       c2  = NULL;
+                       ret = __js_teq(ast, &c2, node);
+                       if (ret < 0)
+                               return ret;
+
+                       c2->basic_block            = c->basic_block;
+                       c2->basic_block->call_flag = 1;
+
+                       scf_list_add_tail(&c->list, &c2->list);
+
+                       assert(1 == c2->dsts->size);
+                       dst = c2->dsts->data[0];
+
+                       src->node = scf_node_clone(dst->node);
+                       if (!src->node)
+                               return -ENOMEM;
+                       src->node->result = dst->node->result;
+                       src->node->op     = dst->node->op;
+               }
+       }
+
+       return 0;
+}
+
+static int _optimize_js_teq(scf_ast_t* ast, scf_function_t* f, scf_vector_t* functions)
+{
+       if (!f)
+               return -EINVAL;
+
+       if (strcmp(f->node.w->text->data, "__js_main")) {
+               scf_string_t* s = f->node.w->file;
+
+               if (!strncmp(s->data + s->len - 8, "js/doc.c", 8))
+                       return 0;
+       }
+
+       printf("\n");
+       scf_logi("------- %s() ------ file: %s\n", f->node.w->text->data, f->node.w->file->data);
+
+       scf_list_t*        bb_list_head = &f->basic_block_list_head;
+       scf_list_t*        l;
+       scf_basic_block_t* bb;
+
+       if (scf_list_empty(bb_list_head))
+               return 0;
+
+       for (l = scf_list_head(bb_list_head); l != scf_list_sentinel(bb_list_head); ) {
+
+               bb = scf_list_data(l, scf_basic_block_t, list);
+               l  = scf_list_next(l);
+
+               if (bb->cmp_flag) {
+
+                       int ret = _optimize_js_teq_bb(ast, f, bb, bb_list_head);
+                       if (ret < 0)
+                               return ret;
+               }
+       }
+
+       return 0;
+}
+
+scf_optimizer_t  scf_optimizer_js_teq =
+{
+       .name     =  "js_teq",
+
+       .optimize =  _optimize_js_teq,
+
+       .flags    = SCF_OPTIMIZER_LOCAL,
+};
index 0fc10ca11ae8a55f7e92ca12f4a05c1531bd84e0..1b0a324345797bc66a78f886be731aedc1f0c204 100644 (file)
@@ -81,7 +81,7 @@ static int _optimize_split_call(scf_ast_t* ast, scf_function_t* f, scf_vector_t*
                bb = scf_list_data(l, scf_basic_block_t, list);
                l  = scf_list_next(l);
 
-               if (bb->jmp_flag || bb->end_flag || bb->cmp_flag)
+               if (bb->jmp_flag || bb->end_flag)
                        continue;
 
                if (!bb->call_flag)
index 3c2fde5450115004f1d98474a69767cd2cb19d9d..469e89640ae017384822ff7fcfe6adc24cff670c 100644 (file)
@@ -134,6 +134,9 @@ scf_variable_t*     scf_variable_alloc(scf_lex_word_t* w, scf_type_t* t)
                                case SCF_LEX_WORD_CONST_CHAR:
                                        v->data.u32 = w->data.u32;
                                        break;
+                               case SCF_LEX_WORD_CONST_BOOL:
+                                       v->data.u32 = w->data.u32;
+                                       break;
 
                                case SCF_LEX_WORD_CONST_STRING:
                                        v->data.s = scf_string_clone(w->data.s);
index 96e695db9bfbd8717902f7aa352a68e3ffb00e99..b6a57eb3331291ccde6fe9d6685e789ab0e38187 100644 (file)
@@ -78,6 +78,7 @@ struct scf_variable_s {
        uint32_t            global_flag :1;
        uint32_t            member_flag :1;
 
+       uint32_t            js_flag     :1;
        uint32_t            vla_flag    :1;
        uint32_t            arg_flag    :1;
        uint32_t            auto_gc_flag:1;
index f509019f793d0dbb4bc56683648cbef7fec3315f..fb4ce0c9eb34e3379e81fea49e94260def71f9e4 100644 (file)
--- a/js/doc.c
+++ b/js/doc.c
@@ -549,6 +549,30 @@ void Object_func_arguments(Object* this, int i, Object* arg)
        }
 }
 
+bool Object_teq(Object* this)
+{
+       if (!this)
+               return 0;
+
+       switch (this->type) {
+               case JS_Number:
+                       return 0.0 != this->d;
+                       break;
+
+               case JS_Boolean:
+                       return 0 != this->i64;
+                       break;
+
+               case JS_String:
+                       return '\0' != this->str[0];
+                       break;
+               default:
+                       break;
+       };
+
+       return 0;
+}
+
 int Object_array_realloc(Object* this, int i)
 {
        if (JS_Object != this->type)
index b59b04499a3f0f0fda5d171096ae5bcc14c3ddc7..ae9e01706bf65f48db8033fd32f8ed7cd56f8170 100644 (file)
@@ -68,6 +68,7 @@ static int _var_add_var(scf_dfa_t* dfa, dfa_data_t* d)
                uint32_t global_flag;
                uint32_t local_flag;
                uint32_t member_flag;
+               uint32_t js_flag = 0;
 
                if (!b) {
                        local_flag  = 0;
@@ -125,6 +126,8 @@ static int _var_add_var(scf_dfa_t* dfa, dfa_data_t* d)
 
                        if (scf_ast_find_type(&id0->type, parse->ast, "Object") < 0)
                                return SCF_DFA_ERROR;
+
+                       js_flag = 1;
                }
 
                v = SCF_VAR_ALLOC_BY_TYPE(id->identity, id0->type, id0->const_flag, id0->nb_pointers, id0->func_ptr);
@@ -135,6 +138,7 @@ static int _var_add_var(scf_dfa_t* dfa, dfa_data_t* d)
                v->local_flag  = local_flag;
                v->global_flag = global_flag;
                v->member_flag = member_flag;
+               v->js_flag     = js_flag;
 
                v->static_flag = id0->static_flag;
                v->extern_flag = id0->extern_flag;
index bad97191352ebc7c8c4ab83890ec0b0726e533e1..95efe611473163638c4823f81b187adbb09e1e7b 100644 (file)
@@ -1863,10 +1863,6 @@ int scf_parse_compile_functions(scf_parse_t* parse, scf_vector_t* functions)
        for (i = 0; i < functions->size; i++) {
                f  =        functions->data[i];
 
-               printf("%d, %p\n", i, f->node.w->text);
-               printf("argv: %p, define_flag: %d, inline_flag: %d\n",
-                               f->argv, f->node.define_flag, f->inline_flag);
-
                printf("%d, %s(), argv->size: %d, define_flag: %d, inline_flag: %d\n",
                                i, f->node.w->text->data, f->argv->size, f->node.define_flag, f->inline_flag);
 
index 902c10ff0400a3e10556cdd92445c7b3e738578d..229ff1d6b2d97e063bc50a0b2a0198d7ca89bf31 100644 (file)
@@ -158,6 +158,7 @@ CFILES += ../js/core/scf_optimizer.c
 CFILES += ../js/core/scf_optimizer_dag.c
 CFILES += ../js/core/scf_optimizer_inline.c
 CFILES += ../js/core/scf_optimizer_js_array.c
+CFILES += ../js/core/scf_optimizer_js_teq.c
 CFILES += ../js/core/scf_optimizer_js_call.c
 CFILES += ../js/core/scf_optimizer_split_call.c
 CFILES += ../js/core/scf_optimizer_call.c