From c5177fa8464ac304547e384583f9c287e124d34a Mon Sep 17 00:00:00 2001 From: normal Date: Wed, 31 Oct 2018 03:02:01 +0000 Subject: mjit: get rid of rb_mjit_unit_node and use ccan/list rb_mjit_unit can either exist in unit_queue or active_units, but not both. This will make state transitions for event-based MJIT process management easier. [ruby-core:89654] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65468 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- mjit_worker.c | 129 +++++++++++++++++----------------------------------------- 1 file changed, 37 insertions(+), 92 deletions(-) (limited to 'mjit_worker.c') diff --git a/mjit_worker.c b/mjit_worker.c index 18ac81d6fc..5008e6d8bc 100644 --- a/mjit_worker.c +++ b/mjit_worker.c @@ -139,18 +139,12 @@ struct rb_mjit_unit { #endif /* Only used by unload_units. Flag to check this unit is currently on stack or not. */ char used_code_p; -}; - -/* Node of linked list in struct rb_mjit_unit_list. - TODO: use ccan/list for this */ -struct rb_mjit_unit_node { - struct rb_mjit_unit *unit; - struct rb_mjit_unit_node *next, *prev; + struct list_node unode; }; /* Linked list of struct rb_mjit_unit. */ struct rb_mjit_unit_list { - struct rb_mjit_unit_node *head; + struct list_head head; int length; /* the list length */ }; @@ -181,11 +175,11 @@ int mjit_call_p = FALSE; /* Priority queue of iseqs waiting for JIT compilation. This variable is a pointer to head unit of the queue. */ -static struct rb_mjit_unit_list unit_queue; +static struct rb_mjit_unit_list unit_queue = { LIST_HEAD_INIT(unit_queue.head) }; /* List of units which are successfully compiled. */ -static struct rb_mjit_unit_list active_units; +static struct rb_mjit_unit_list active_units = { LIST_HEAD_INIT(active_units.head) }; /* List of compacted so files which will be deleted in `mjit_finish()`. */ -static struct rb_mjit_unit_list compact_units; +static struct rb_mjit_unit_list compact_units = { LIST_HEAD_INIT(compact_units.head) }; /* The number of so far processed ISEQs, used to generate unique id. */ static int current_unit_num; /* A mutex for conitionals and critical sections. */ @@ -318,57 +312,20 @@ mjit_warning(const char *format, ...) } } -/* Allocate struct rb_mjit_unit_node and return it. This MUST NOT be - called inside critical section because that causes deadlock. ZALLOC - may fire GC and GC hooks mjit_gc_start_hook that starts critical section. */ -static struct rb_mjit_unit_node * -create_list_node(struct rb_mjit_unit *unit) -{ - struct rb_mjit_unit_node *node = calloc(1, sizeof(struct rb_mjit_unit_node)); /* To prevent GC, don't use ZALLOC */ - if (node == NULL) return NULL; - node->unit = unit; - return node; -} - /* Add unit node to the tail of doubly linked LIST. It should be not in the list before. */ static void -add_to_list(struct rb_mjit_unit_node *node, struct rb_mjit_unit_list *list) +add_to_list(struct rb_mjit_unit *unit, struct rb_mjit_unit_list *list) { - /* Append iseq to list */ - if (list->head == NULL) { - list->head = node; - } - else { - struct rb_mjit_unit_node *tail = list->head; - while (tail->next != NULL) { - tail = tail->next; - } - tail->next = node; - node->prev = tail; - } + list_add_tail(&list->head, &unit->unode); list->length++; } static void -remove_from_list(struct rb_mjit_unit_node *node, struct rb_mjit_unit_list *list) +remove_from_list(struct rb_mjit_unit *unit, struct rb_mjit_unit_list *list) { - if (node->prev && node->next) { - node->prev->next = node->next; - node->next->prev = node->prev; - } - else if (node->prev == NULL && node->next) { - list->head = node->next; - node->next->prev = NULL; - } - else if (node->prev && node->next == NULL) { - node->prev->next = NULL; - } - else { - list->head = NULL; - } + list_del(&unit->unode); list->length--; - free(node); } static void @@ -497,28 +454,26 @@ mjit_valid_class_serial_p(rb_serial_t class_serial) /* Return the best unit from list. The best is the first high priority unit or the unit whose iseq has the biggest number of calls so far. */ -static struct rb_mjit_unit_node * +static struct rb_mjit_unit * get_from_list(struct rb_mjit_unit_list *list) { - struct rb_mjit_unit_node *node, *next, *best = NULL; - - if (list->head == NULL) - return NULL; + struct rb_mjit_unit *unit = NULL, *next, *best = NULL; /* Find iseq with max total_calls */ - for (node = list->head; node != NULL; node = next) { - next = node->next; - if (node->unit->iseq == NULL) { /* ISeq is GCed. */ - free_unit(node->unit); - remove_from_list(node, list); + list_for_each_safe(&list->head, unit, next, unode) { + if (unit->iseq == NULL) { /* ISeq is GCed. */ + remove_from_list(unit, list); + free_unit(unit); continue; } - if (best == NULL || best->unit->iseq->body->total_calls < node->unit->iseq->body->total_calls) { - best = node; + if (best == NULL || best->iseq->body->total_calls < unit->iseq->body->total_calls) { + best = unit; } } - + if (best) { + remove_from_list(best, list); + } return best; } @@ -881,8 +836,7 @@ static void compact_all_jit_code(void) { # ifndef _WIN32 /* This requires header transformation but we don't transform header on Windows for now */ - struct rb_mjit_unit *unit; - struct rb_mjit_unit_node *node; + struct rb_mjit_unit *unit, *cur = 0; double start_time, end_time; static const char so_ext[] = DLEXT; char so_file[MAXPATHLEN]; @@ -899,8 +853,8 @@ compact_all_jit_code(void) o_files = alloca(sizeof(char *) * (active_units.length + 1)); o_files[active_units.length] = NULL; CRITICAL_SECTION_START(3, "in compact_all_jit_code to keep .o files"); - for (node = active_units.head; node != NULL; node = node->next) { - o_files[i] = node->unit->o_file; + list_for_each(&active_units.head, cur, unode) { + o_files[i] = cur->o_file; i++; } @@ -924,27 +878,25 @@ compact_all_jit_code(void) unit->handle = handle; /* lazily dlclose handle (and .so file for win32) on `mjit_finish()`. */ - node = calloc(1, sizeof(struct rb_mjit_unit_node)); /* To prevent GC, don't use ZALLOC */ - node->unit = unit; - add_to_list(node, &compact_units); + add_to_list(unit, &compact_units); if (!mjit_opts.save_temps) remove_so_file(so_file, unit); CRITICAL_SECTION_START(3, "in compact_all_jit_code to read list"); - for (node = active_units.head; node != NULL; node = node->next) { + list_for_each(&active_units.head, cur, unode) { void *func; char funcname[35]; /* TODO: reconsider `35` */ - sprintf(funcname, "_mjit%d", node->unit->id); + sprintf(funcname, "_mjit%d", cur->id); if ((func = dlsym(handle, funcname)) == NULL) { mjit_warning("skipping to reload '%s' from '%s': %s", funcname, so_file, dlerror()); continue; } - if (node->unit->iseq) { /* Check whether GCed or not */ + if (cur->iseq) { /* Check whether GCed or not */ /* Usage of jit_code might be not in a critical section. */ - MJIT_ATOMIC_SET(node->unit->iseq->body->jit_func, (mjit_func_t)func); + MJIT_ATOMIC_SET(cur->iseq->body->jit_func, (mjit_func_t)func); } } CRITICAL_SECTION_FINISH(3, "in compact_all_jit_code to read list"); @@ -1146,14 +1098,8 @@ convert_unit_to_func(struct rb_mjit_unit *unit, struct rb_call_cache *cc_entries remove_so_file(so_file, unit); if ((uintptr_t)func > (uintptr_t)LAST_JIT_ISEQ_FUNC) { - struct rb_mjit_unit_node *node = create_list_node(unit); - if (node == NULL) { - mjit_warning("failed to allocate a node to be added to active_units"); - return (mjit_func_t)NOT_COMPILED_JIT_ISEQ_FUNC; - } - CRITICAL_SECTION_START(3, "end of jit"); - add_to_list(node, &active_units); + add_to_list(unit, &active_units); if (unit->iseq) print_jit_result("success", unit, end_time - start_time, c_file); CRITICAL_SECTION_FINISH(3, "end of jit"); @@ -1216,22 +1162,22 @@ mjit_worker(void) /* main worker loop */ while (!stop_worker_p) { - struct rb_mjit_unit_node *node; + struct rb_mjit_unit *unit; /* wait until unit is available */ CRITICAL_SECTION_START(3, "in worker dequeue"); - while ((unit_queue.head == NULL || active_units.length >= mjit_opts.max_cache_size) && !stop_worker_p) { + while ((list_empty(&unit_queue.head) || active_units.length >= mjit_opts.max_cache_size) && !stop_worker_p) { rb_native_cond_wait(&mjit_worker_wakeup, &mjit_engine_mutex); verbose(3, "Getting wakeup from client"); } - node = get_from_list(&unit_queue); + unit = get_from_list(&unit_queue); CRITICAL_SECTION_FINISH(3, "in worker dequeue"); - if (node) { + if (unit) { mjit_func_t func; struct mjit_copy_job job; - job.body = node->unit->iseq->body; + job.body = unit->iseq->body; job.cc_entries = NULL; if (job.body->ci_size > 0 || job.body->ci_kw_size > 0) job.cc_entries = alloca(sizeof(struct rb_call_cache) * (job.body->ci_size + job.body->ci_kw_size)); @@ -1250,14 +1196,13 @@ mjit_worker(void) } /* JIT compile */ - func = convert_unit_to_func(node->unit, job.cc_entries, job.is_entries); + func = convert_unit_to_func(unit, job.cc_entries, job.is_entries); CRITICAL_SECTION_START(3, "in jit func replace"); - if (node->unit->iseq) { /* Check whether GCed or not */ + if (unit->iseq) { /* Check whether GCed or not */ /* Usage of jit_code might be not in a critical section. */ - MJIT_ATOMIC_SET(node->unit->iseq->body->jit_func, func); + MJIT_ATOMIC_SET(unit->iseq->body->jit_func, func); } - remove_from_list(node, &unit_queue); CRITICAL_SECTION_FINISH(3, "in jit func replace"); #ifndef _MSC_VER -- cgit v1.2.3