+#include"scf_optimizer.h"
+#include"scf_pointer_alias.h"
+
+static int __js_array_index(scf_ast_t* ast, scf_3ac_code_t* c, scf_dag_node_t* index, scf_type_t* Object)
+{
+ scf_3ac_operand_t* pf;
+ scf_variable_t* v;
+ scf_dag_node_t* dn;
+ scf_function_t* f = NULL;
+ scf_type_t* t = NULL;
+
+ int ret;
+
+ if (SCF_OP_3AC_ASSIGN_ARRAY_INDEX == c->op->type)
+ ret = scf_ast_find_global_function(&f, ast, "Object_assign_array_index_obj");
+ else {
+ if (index->var->type == Object->type)
+ ret = scf_ast_find_global_function(&f, ast, "Object_array_index_obj");
+
+ else if (index->var->type == SCF_VAR_DOUBLE)
+ ret = scf_ast_find_global_function(&f, ast, "Object_array_index_d");
+ else
+ ret = scf_ast_find_global_function(&f, ast, "Object_array_index");
+ }
+ 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;
+
+ dn = scf_dag_node_alloc(v->type, v, (scf_node_t*)f);
+ scf_variable_free(v);
+ v = NULL;
+ if (!dn)
+ return -ENOMEM;
+
+ pf = c->srcs->data[2];
+
+ if (pf->node)
+ scf_node_free(pf->node);
+
+ if (pf->dag_node) {
+ scf_list_del(&pf->dag_node->list);
+ scf_dag_node_free(pf->dag_node);
+ }
+
+ pf->node = (scf_node_t*)f;
+ pf->dag_node = dn;
+
+ SCF_XCHG(c->srcs->data[2], c->srcs->data[1]);
+ SCF_XCHG(c->srcs->data[1], c->srcs->data[0]);
+
+ c->op = scf_3ac_find_operator(SCF_OP_CALL);
+ return 0;
+}
+
+static scf_3ac_code_t* __js_array_find_3ac(scf_dag_node_t* member, scf_3ac_code_t* c, scf_basic_block_t* cur_bb, scf_basic_block_t* bb, scf_list_t* l, scf_list_t* bb_list_head)
+{
+ scf_basic_block_t* bb2;
+ scf_3ac_operand_t* dst;
+ scf_3ac_code_t* c2;
+ scf_list_t* l2;
+ scf_list_t* l3;
+
+ for (l2 = scf_list_prev(&c->list); l2 != scf_list_sentinel(&cur_bb->code_list_head); l2 = scf_list_prev(l2)) {
+ c2 = scf_list_data(l2, scf_3ac_code_t, list);
+
+ if (SCF_OP_POINTER == c2->op->type) {
+ dst = c2->dsts->data[0];
+
+ if (dst->dag_node == member)
+ return c2;
+ }
+ }
+
+ for (l3 = scf_list_prev(&cur_bb->list); l3 != scf_list_sentinel(bb_list_head); l3 = scf_list_prev(l3)) {
+ bb2 = scf_list_data(l3, scf_basic_block_t, list);
+
+ if (bb2 == bb) {
+ l2 = scf_list_prev(l);
+
+ if (l2 == &c->list)
+ l2 = scf_list_prev(l2);
+ } else
+ l2 = scf_list_tail(&bb2->code_list_head);
+
+ for ( ; l2 != scf_list_sentinel(&bb2->code_list_head); l2 = scf_list_prev(l2)) {
+ c2 = scf_list_data(l2, scf_3ac_code_t, list);
+
+ if (SCF_OP_POINTER == c2->op->type) {
+ dst = c2->dsts->data[0];
+
+ if (dst->dag_node == member)
+ return c2;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+static int _optimize_js_array2_bb(scf_ast_t* ast, scf_function_t* f, scf_basic_block_t* bb, scf_list_t* bb_list_head)
+{
+ scf_basic_block_t* cur_bb = bb;
+ scf_basic_block_t* bb2;
+ scf_basic_block_t* bb3;
+
+ scf_3ac_operand_t* base;
+ scf_3ac_operand_t* index;
+ scf_3ac_code_t* c;
+ scf_3ac_code_t* c2;
+ scf_dag_node_t* array;
+ scf_dag_node_t* member;
+ scf_type_t* Object = NULL;
+ scf_list_t* l;
+ scf_list_t* l2;
+
+ 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 (cur_bb != bb) {
+ scf_list_del(&c->list);
+ scf_list_add_tail(&cur_bb->code_list_head, &c->list);
+
+ c->basic_block = cur_bb;
+ }
+
+ if (SCF_OP_ARRAY_INDEX != c->op->type && SCF_OP_3AC_ASSIGN_ARRAY_INDEX != c->op->type)
+ continue;
+
+ base = c->srcs->data[0];
+ index = c->srcs->data[1];
+ member = base->dag_node;
+
+ array = member;
+ while (SCF_OP_EXPR == array->type || SCF_OP_POINTER == array->type)
+ array = array->childs->data[0];
+
+ if (array->var->type != Object->type)
+ continue;
+
+ if (SCF_OP_3AC_ASSIGN_ARRAY_INDEX == c->op->type && index->dag_node->var->type != Object->type)
+ continue;
+
+ int op_type = c->op->type;
+
+ ret = __js_array_index(ast, c, index->dag_node, Object);
+ if (ret < 0)
+ return ret;
+
+ scf_vector_del(c->basic_block->dn_reloads, member);
+
+ base = c->srcs->data[1];
+ base->dag_node = array;
+ base->node = array->node;
+#if 1
+ c2 = __js_array_find_3ac(member, c, cur_bb, bb, l, bb_list_head);
+ assert(c2);
+
+ scf_vector_del(c2->basic_block->dn_resaves, member);
+ scf_vector_del(c2->basic_block->exit_dn_actives, member);
+
+ scf_list_del(&c2->list);
+ scf_3ac_code_free(c2);
+ c2 = NULL;
+#endif
+
+ if (scf_list_prev(&c->list) != scf_list_sentinel(&cur_bb->code_list_head)) {
+ bb2 = NULL;
+ ret = scf_basic_block_split(cur_bb, &bb2);
+ if (ret < 0)
+ return ret;
+ scf_list_add_front(&cur_bb->list, &bb2->list);
+
+ if (SCF_OP_ARRAY_INDEX == op_type) {
+ base = c->dsts->data[0];
+ scf_vector_del(cur_bb->dn_resaves, base->dag_node);
+ scf_vector_del(cur_bb->exit_dn_actives, base->dag_node);
+
+ base = c->srcs->data[2];
+ scf_vector_del(cur_bb->dn_reloads, base->dag_node);
+ }
+
+ scf_list_del(&c->list);
+ scf_list_add_tail(&bb2->code_list_head, &c->list);
+
+ c->basic_block = bb2;
+
+ if (l != scf_list_sentinel(&bb->code_list_head)) {
+ bb3 = NULL;
+ ret = scf_basic_block_split(bb2, &bb3);
+ if (ret < 0)
+ return ret;
+ scf_list_add_front(&bb2->list, &bb3->list);
+
+ bb3->ret_flag = bb->ret_flag;
+
+ cur_bb = bb3;
+ }
+ }
+
+ c->basic_block->call_flag = 1;
+ }
+
+ return 0;
+}
+
+static int _optimize_js_array2(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->jmp_flag || bb->end_flag || bb->cmp_flag)
+ continue;
+
+ int ret = _optimize_js_array2_bb(ast, f, bb, bb_list_head);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+scf_optimizer_t scf_optimizer_js_array2 =
+{
+ .name = "js_array2",
+
+ .optimize = _optimize_js_array2,
+
+ .flags = SCF_OPTIMIZER_LOCAL,
+};