From 30111e5cf6ff5a7766296ac2579a98c16e7cc7c1 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sat, 2 Jun 2018 11:07:27 +0200 Subject: Computed the initial lines width using all threads. --- src/analysis/binary.c | 10 ++ src/glibext/gbuffercache.c | 10 +- src/glibext/gbuffercache.h | 2 +- src/glibext/gbufferview.c | 26 ++-- src/glibext/gwidthtracker.c | 361 +++++++++++++++++++++++++++++++++++++++++++- src/glibext/gwidthtracker.h | 7 + 6 files changed, 395 insertions(+), 21 deletions(-) diff --git a/src/analysis/binary.c b/src/analysis/binary.c index 15ec403..54ad89b 100644 --- a/src/analysis/binary.c +++ b/src/analysis/binary.c @@ -1625,6 +1625,7 @@ static bool g_loaded_binary_analyze(GLoadedBinary *binary, wgroup_id_t gid, GtkS const char *arch; /* Architecture d'exécution */ const char *desc; /* Description humaine associée*/ GProcContext *context; /* Contexte de suivi dédié */ + GWidthTracker *tracker; /* Gestionnaire de largeur */ /* Interprétation du format associé */ @@ -1663,8 +1664,17 @@ static bool g_loaded_binary_analyze(GLoadedBinary *binary, wgroup_id_t gid, GtkS g_binary_format_complete_analysis(format, gid, status); if (!is_batch_mode()) + { output_disassembly(binary, context, status, &binary->disass_cache); + tracker = g_buffer_cache_get_width_tracker(binary->disass_cache); + + g_width_tracker_build_initial_cache(tracker, gid, status); + + g_object_unref(G_OBJECT(tracker)); + + } + result = true; glba_exit: diff --git a/src/glibext/gbuffercache.c b/src/glibext/gbuffercache.c index a627238..66ecf27 100644 --- a/src/glibext/gbuffercache.c +++ b/src/glibext/gbuffercache.c @@ -784,9 +784,15 @@ size_t g_buffer_cache_count_lines(const GBufferCache *cache) * * ******************************************************************************/ -const GWidthTracker *g_buffer_cache_get_width_tracker(const GBufferCache *cache) +GWidthTracker *g_buffer_cache_get_width_tracker(const GBufferCache *cache) { - return cache->tracker; + GWidthTracker *result; /* Instance à retourner * */ + + result = cache->tracker; + + g_object_ref(G_OBJECT(result)); + + return result; } diff --git a/src/glibext/gbuffercache.h b/src/glibext/gbuffercache.h index c00e0f2..dbd3237 100644 --- a/src/glibext/gbuffercache.h +++ b/src/glibext/gbuffercache.h @@ -72,7 +72,7 @@ gint g_buffer_cache_get_text_position(const GBufferCache *); size_t g_buffer_cache_count_lines(const GBufferCache *); /* Fournit un lien vers la structure de suivi de largeurs. */ -const GWidthTracker *g_buffer_cache_get_width_tracker(const GBufferCache *); +GWidthTracker *g_buffer_cache_get_width_tracker(const GBufferCache *); /* Insère un générateur dans des lignes à une position donnée. */ void g_buffer_cache_insert_at(GBufferCache *, size_t, GLineGenerator *, bool, bool); diff --git a/src/glibext/gbufferview.c b/src/glibext/gbufferview.c index c212672..af7d7ac 100644 --- a/src/glibext/gbufferview.c +++ b/src/glibext/gbufferview.c @@ -45,12 +45,7 @@ struct _GBufferView size_t first; /* Indice de la première ligne */ size_t last; /* Indice de la dernière ligne */ - union - { - const GWidthTracker *ext_tracker; /* Suivi externe des largeurs */ - GWidthTracker *int_tracker; /* Suivi interne des largeurs */ - GWidthTracker *tracker; /* Suivi pour usage interne */ - }; + GWidthTracker *tracker; /* Suivi des largeurs */ }; @@ -173,8 +168,7 @@ static void g_buffer_view_dispose(GBufferView *view) { g_object_unref(G_OBJECT(view->cache)); - if (!view->unrestricted) - g_object_unref(G_OBJECT(view->int_tracker)); + g_object_unref(G_OBJECT(view->tracker)); G_OBJECT_CLASS(g_buffer_view_parent_class)->dispose(G_OBJECT(view)); @@ -400,7 +394,7 @@ GBufferCache *g_buffer_view_get_cache(const GBufferView *view) void g_buffer_view_restrict(GBufferView *view, const vmpa2t *start, const vmpa2t *end) { bool state; /* Nouvel état à proclamer */ - const GWidthTracker *template; /* Suivi déjà en place */ + GWidthTracker *template; /* Suivi déjà en place */ state = (start == NULL || end == NULL); @@ -410,16 +404,16 @@ void g_buffer_view_restrict(GBufferView *view, const vmpa2t *start, const vmpa2t template = g_buffer_cache_get_width_tracker(view->cache); + /* Vérification pour le cas particulier du démarrage */ + if (view->tracker != NULL) + g_object_unref(G_OBJECT(view->tracker)); + if (view->unrestricted) { - /* Vérification pour le cas particulier du démarrage */ - if (view->int_tracker != NULL) - g_object_unref(G_OBJECT(view->int_tracker)); - view->first = 0; view->last = g_buffer_cache_count_lines(view->cache) - 1; - view->ext_tracker = template; + view->tracker = template; } @@ -431,7 +425,9 @@ void g_buffer_view_restrict(GBufferView *view, const vmpa2t *start, const vmpa2t view->first = g_buffer_cache_find_index_by_addr(view->cache, start, true); view->last = g_buffer_cache_find_index_by_addr(view->cache, end, false); - view->ext_tracker = g_width_tracker_new_restricted(template, view->first, view->last); + view->tracker = g_width_tracker_new_restricted(template, view->first, view->last); + + g_object_unref(G_OBJECT(template)); } diff --git a/src/glibext/gwidthtracker.c b/src/glibext/gwidthtracker.c index 82ae65b..181759c 100644 --- a/src/glibext/gwidthtracker.c +++ b/src/glibext/gwidthtracker.c @@ -30,8 +30,77 @@ #include +#include + + +#include "delayed-int.h" #include "gbuffercache.h" +#include "../core/global.h" + + + +/* --------------------------- PRISE DE MESURES INITIALES --------------------------- */ + + +/* Procédure de mise à jour des mesures de largeurs (instance) */ +typedef struct _GWidthUpdate +{ + GDelayedWork parent; /* A laisser en premier */ + + activity_id_t id; /* Groupe de progression */ + + GWidthTracker *tracker; /* Gestionnaire à manipuler */ + + size_t start; /* Premier indice à traiter */ + size_t end; /* Premier indice à écarter */ + + line_width_summary summary; /* Largeurs requises suivies */ + +} GWidthUpdate; + +/* Procédure de mise à jour des mesures de largeurs (classe) */ +typedef struct _GWidthUpdateClass +{ + GDelayedWorkClass parent; /* A laisser en premier */ + +} GWidthUpdateClass; + + +#define G_TYPE_WIDTH_UPDATE g_width_update_get_type() +#define G_WIDTH_UPDATE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_WIDTH_UPDATE, GWidthUpdate)) +#define G_IS_WIDTH_UPDATE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_WIDTH_UPDATE)) +#define G_WIDTH_UPDATE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_WIDTH_UPDATE, GWidthUpdateClass)) +#define G_IS_WIDTH_UPDATE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_WIDTH_UPDATE)) +#define G_WIDTH_UPDATE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_WIDTH_UPDATE, GWidthUpdateClass)) + + +/* Initialise la classe des tâches de mesures de largeurs. */ +static void g_width_update_class_init(GWidthUpdateClass *); + +/* Initialise une tâche de mesures de largeurs. */ +static void g_width_update_init(GWidthUpdate *); + +/* Supprime toutes les références externes. */ +static void g_width_update_dispose(GWidthUpdate *); + +/* Procède à la libération totale de la mémoire. */ +static void g_width_update_finalize(GWidthUpdate *); + +/* Indique le type défini pour les tâches de mesures de largeurs. */ +GType g_width_update_get_type(void); + +/* Crée une tâche de mesures de largeurs. */ +static GWidthUpdate *g_width_update_new(activity_id_t, GWidthTracker *, size_t, size_t); +/* Assure les mesures initiales d'un ensemble de lignes. */ +static void g_width_update_process(GWidthUpdate *, GtkStatusStack *); + +/* Récupère les données obtenues lors d'une mesure globale. */ +static void g_width_update_collect(GWidthUpdate *, line_width_summary *); + + + +/* ---------------------------- RASSEMBLEMENT DE MESURES ---------------------------- */ /* Portions de largeurs communes */ @@ -98,6 +167,209 @@ static void g_width_tracker_ensure_valid_required_widths(GWidthTracker *); +/* ---------------------------------------------------------------------------------- */ +/* PRISE DE MESURES INITIALES */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour les tâches de mesures de largeurs. */ +G_DEFINE_TYPE(GWidthUpdate, g_width_update, G_TYPE_DELAYED_WORK); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des tâches de mesures de largeurs. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_width_update_class_init(GWidthUpdateClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GDelayedWorkClass *work; /* Version en classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_width_update_dispose; + object->finalize = (GObjectFinalizeFunc)g_width_update_finalize; + + work = G_DELAYED_WORK_CLASS(klass); + + work->run = (run_task_fc)g_width_update_process; + +} + + +/****************************************************************************** +* * +* Paramètres : update = instance à initialiser. * +* * +* Description : Initialise une tâche de mesures de largeurs. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_width_update_init(GWidthUpdate *update) +{ + memset(&update->summary, 0, sizeof(line_width_summary)); + +} + + +/****************************************************************************** +* * +* Paramètres : update = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_width_update_dispose(GWidthUpdate *update) +{ + g_object_unref(G_OBJECT(update->tracker)); + + G_OBJECT_CLASS(g_width_update_parent_class)->dispose(G_OBJECT(update)); + +} + + +/****************************************************************************** +* * +* Paramètres : update = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_width_update_finalize(GWidthUpdate *update) +{ + G_OBJECT_CLASS(g_width_update_parent_class)->finalize(G_OBJECT(update)); + +} + + +/****************************************************************************** +* * +* Paramètres : id = identifiant pour signaler la progression courante. * +* tracker = gestionnaire de largeurs à consulter. * +* start = indice de la première ligne à traiter. * +* end = indice de la première ligne à éviter. * +* * +* Description : Crée une tâche de mesures de largeurs. * +* * +* Retour : Tâche créée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GWidthUpdate *g_width_update_new(activity_id_t id, GWidthTracker *tracker, size_t start, size_t end) +{ + GWidthUpdate *result; /* Tâche à retourner */ + + result = g_object_new(G_TYPE_WIDTH_UPDATE, NULL); + + result->id = id; + + g_object_ref(G_OBJECT(tracker)); + result->tracker = tracker; + + result->start = start; + result->end = end; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : update = opération de mesures à mener. * +* status = barre de statut à tenir informée. * +* * +* Description : Assure les mesures initiales d'un ensemble de lignes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_width_update_process(GWidthUpdate *update, GtkStatusStack *status) +{ + line_width_summary *local; /* Valeurs collectées */ + size_t i; /* Boucle de parcours #1 */ + const line_width_summary *summary; /* Valeurs à intégrer */ + BufferLineColumn k; /* Boucle de parcours #2 */ + + local = &update->summary; + + for (i = update->start; i < update->end; i++) + { + summary = g_width_tracker_get_up_to_date_widths(update->tracker, i); + + for (k = 0; k < BLC_COUNT; k++) + local->max_widths[k] = MAX(local->max_widths[k], summary->max_widths[k]); + + local->merged_width = MAX(local->merged_width, summary->merged_width); + + gtk_status_stack_update_activity_value(status, update->id, 1); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : update = opération de mesures menée à bien. * +* global = lieu de centralisation des données globales. * +* * +* Description : Récupère les données obtenues lors d'une mesure globale. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_width_update_collect(GWidthUpdate *update, line_width_summary *global) +{ + line_width_summary *local; /* Valeurs collectées */ + BufferLineColumn i; /* Boucle de parcours */ + + local = &update->summary; + + for (i = 0; i < BLC_COUNT; i++) + global->max_widths[i] = MAX(global->max_widths[i], local->max_widths[i]); + + global->merged_width = MAX(global->merged_width, local->merged_width); + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* RASSEMBLEMENT DE MESURES */ +/* ---------------------------------------------------------------------------------- */ + + /* Détermine le type du gestionnaire de largeurs associées aux lignes. */ G_DEFINE_TYPE(GWidthTracker, g_width_tracker, G_TYPE_OBJECT); @@ -686,6 +958,89 @@ void g_width_tracker_update_deleted(GWidthTracker *tracker, size_t start, size_t /****************************************************************************** * * +* Paramètres : tracker = suivi de largeurs dont le cache est à construire. * +* gid = groupe de travail impliqué. * +* status = barre de statut à tenir informée. * +* * +* Description : Calcule les largeurs requises par un ensemble de lignes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_width_tracker_build_initial_cache(GWidthTracker *tracker, wgroup_id_t gid, GtkStatusStack *status) +{ + guint runs_count; /* Qté d'exécutions parallèles */ + GWidthUpdate **updates; /* Mesures à suivre */ + size_t run_size; /* Volume réparti par exécution*/ + GWorkQueue *queue; /* Gestionnaire de différés */ + activity_id_t id; /* Identifiant de progression */ + guint i; /* Boucle de parcours */ + size_t start; /* Début de zone de traitement */ + bool closing; /* Détection de fin en amont */ + size_t end; /* Fin de zone de traitement */ + + assert(!tracker->cached); + + /* Lancement des traitements */ + + runs_count = g_get_num_processors(); + + updates = (GWidthUpdate **)calloc(runs_count, sizeof(GWidthUpdate *)); + + run_size = tracker->count / runs_count; + + queue = get_work_queue(); + + id = gtk_status_stack_add_activity(status, _("Computing width of all lines for rendering"), tracker->count); + + for (i = 0; i < runs_count; i++) + { + start = i * run_size; + + closing = ((i + 1) == runs_count); + + if (closing) + end = tracker->count; + else + end = start + run_size; + + updates[i] = g_width_update_new(id, tracker, start, end); + + g_object_ref(G_OBJECT(updates[i])); + g_work_queue_schedule_work(queue, G_DELAYED_WORK(updates[i]), gid); + + } + + g_work_queue_wait_for_completion(queue, gid); + + /* Récupération des aires */ + + memset(&tracker->summary, 0, sizeof(line_width_summary)); + + for (i = 0; i < runs_count; i++) + { + g_width_update_collect(updates[i], &tracker->summary); + + g_object_unref(G_OBJECT(updates[i])); + + } + + /* Fin */ + + free(updates); + + gtk_status_stack_remove_activity(status, id); + + tracker->cached = true; + +} + + +/****************************************************************************** +* * * Paramètres : tracker = suivi de largeurs à mettre à jour si besoin est. * * * * Description : Calcule les largeurs requises par un ensemble de lignes. * @@ -705,14 +1060,14 @@ static void g_width_tracker_ensure_valid_required_widths(GWidthTracker *tracker) if (!tracker->cached) { + global = &tracker->summary; + /* Réinitialisation */ - memset(&tracker->summary, 0, sizeof(line_width_summary)); + memset(global, 0, sizeof(line_width_summary)); /* Collecte */ - global = &tracker->summary; - for (i = 0; i < tracker->count; i++) { summary = g_width_tracker_get_up_to_date_widths(tracker, i); diff --git a/src/glibext/gwidthtracker.h b/src/glibext/gwidthtracker.h index 0832467..2d9aef6 100644 --- a/src/glibext/gwidthtracker.h +++ b/src/glibext/gwidthtracker.h @@ -29,10 +29,14 @@ #include +#include "delayed.h" #include "gbufferline.h" +/* ---------------------------- RASSEMBLEMENT DE MESURES ---------------------------- */ + + /* gbuffercache.h : Tampon pour gestion de lignes optimisée (instance) */ typedef struct _GBufferCache GBufferCache; @@ -70,6 +74,9 @@ void g_width_tracker_update_added(GWidthTracker *, size_t, size_t); /* Prend acte de la suppression de lignes pour les largeurs. */ void g_width_tracker_update_deleted(GWidthTracker *, size_t, size_t); +/* Calcule les largeurs requises par un ensemble de lignes. */ +void g_width_tracker_build_initial_cache(GWidthTracker *, wgroup_id_t, GtkStatusStack *); + /* Fournit un bon résumé des largeurs en vigueur. */ const line_width_summary *g_width_tracker_get_width_summary(GWidthTracker *); -- cgit v0.11.2-87-g4458