On Thu, Nov 15, 2012 at 04:13:01PM +0000, Nicholas Clark wrote:
> Following a chat on IRC today:
> 
> 09:28 < nwc10> I see accesses to all structure members except constraints in 
>                the rest of the code
> 09:29 < jnthn> Yeah. It could be moved into Rakudo_md_candidate_graph_node if 
>                it's only used in the sort.
> 09:30 < nwc10> aha. good plan. I'd not thought of doing it like that.
> 
> http://irclog.perlgeek.de/perl6/2012-11-15#i_6155821
> 
> 
> Is this attached patch the way to go?

After chat on IRC, this is an improved version. I forgot to send it anywhere
Specifically, we both think that using lots of parameters is ugly.
Improved version passes in a Rakudo_md_candidate_graph_node instead of using
Rakudo_md_candidate_info

> -=item C<static INTVAL is_narrower(PARROT_INTERP, Rakudo_md_candidate_info 
> *a, Rakudo_md_candidate_info *b)>
> +=item C<static INTVAL is_narrower(PARROT_INTERP, Rakudo_md_candidate_info 
> *a, PMC **a_constraints, Rakudo_md_candidate_info *b, PMC **b_constraints)>

Nicholas Clark
>From 77bd81d5a2ef1c1d27ddc418469e4a60d88e7a86 Mon Sep 17 00:00:00 2001
From: Nicholas Clark <n...@ccl4.org>
Date: Thu, 15 Nov 2012 16:52:33 +0100
Subject: [PATCH] Move constraints from Rakudo_md_candidate_info to
 Rakudo_md_candidate_graph_node as it's only needed while generating the
 sorted candidate list.

---
 src/binder/multidispatch.c | 46 ++++++++++++++++++++++++++--------------------
 src/binder/multidispatch.h |  3 ++-
 2 files changed, 28 insertions(+), 21 deletions(-)

diff --git a/src/binder/multidispatch.c b/src/binder/multidispatch.c
index 31bba2f..baec088 100644
--- a/src/binder/multidispatch.c
+++ b/src/binder/multidispatch.c
@@ -40,7 +40,7 @@ This implements Perl 6 multiple dispatch.
 
 =over 4
 
-=item C<static INTVAL is_narrower(PARROT_INTERP, Rakudo_md_candidate_info *a, Rakudo_md_candidate_info *b)>
+=item C<static INTVAL is_narrower(PARROT_INTERP, Rakudo_md_candidate_graph_node *a, Rakudo_md_candidate_graph_node *b)>
 
 Takes two candidates and determines if the first one is narrower than the
 second. Returns a true value if they are.
@@ -48,26 +48,30 @@ second. Returns a true value if they are.
 =cut
 
 */
-static INTVAL is_narrower(PARROT_INTERP, Rakudo_md_candidate_info *a, Rakudo_md_candidate_info *b) {
+static INTVAL is_narrower(PARROT_INTERP,
+                          Rakudo_md_candidate_graph_node *a,
+                          Rakudo_md_candidate_graph_node *b) {
     INTVAL narrower = 0;
     INTVAL tied = 0;
     INTVAL i, types_to_check;
+    Rakudo_md_candidate_info *const a_info = a->info;
+    Rakudo_md_candidate_info *const b_info = b->info;
 
     /* Work out how many parameters to compare, factoring in slurpiness
      * and optionals. */
-    if (a->num_types == b->num_types)
-        types_to_check = a->num_types;
-    else if (a->min_arity == b->min_arity)
-        types_to_check = a->num_types > b->num_types ? b->num_types : a->num_types;
-    else if (a->max_arity != SLURPY_ARITY && b->max_arity == SLURPY_ARITY)
+    if (a_info->num_types == b_info->num_types)
+        types_to_check = a_info->num_types;
+    else if (a_info->min_arity == b_info->min_arity)
+        types_to_check = a_info->num_types > b_info->num_types ? b_info->num_types : a_info->num_types;
+    else if (a_info->max_arity != SLURPY_ARITY && b_info->max_arity == SLURPY_ARITY)
         return 1;
     else
         return 0;
 
     /* Analyse each parameter in the two candidates. */
     for (i = 0; i < types_to_check; i++) {
-        PMC * const type_obj_a = a->types[i];
-        PMC * const type_obj_b = b->types[i];
+        PMC * const type_obj_a = a_info->types[i];
+        PMC * const type_obj_b = b_info->types[i];
         if (type_obj_a == type_obj_b) {
             /* Same type; narrower if first has constraints and other doesn't;
              * tied if neither has constraints or both have constraints. */
@@ -78,12 +82,12 @@ static INTVAL is_narrower(PARROT_INTERP, Rakudo_md_candidate_info *a, Rakudo_md_
                     (!PMC_IS_NULL(a->constraints[i]) && !PMC_IS_NULL(b->constraints[i])))
                 tied++;
         }
-        else if ((a->type_flags[i] & TYPE_NATIVE_MASK) && !(b->type_flags[i] & TYPE_NATIVE_MASK))
+        else if ((a_info->type_flags[i] & TYPE_NATIVE_MASK) && !(b_info->type_flags[i] & TYPE_NATIVE_MASK))
         {
             /* Narrower because natives always are. */
             narrower++;
         }
-        else if ((b->type_flags[i] & TYPE_NATIVE_MASK) && !(a->type_flags[i] & TYPE_NATIVE_MASK))
+        else if ((b_info->type_flags[i] & TYPE_NATIVE_MASK) && !(a_info->type_flags[i] & TYPE_NATIVE_MASK))
         {
             /* Wider; skip over here so we don't go counting this as tied in
              * the next branch. */
@@ -112,15 +116,15 @@ static INTVAL is_narrower(PARROT_INTERP, Rakudo_md_candidate_info *a, Rakudo_md_
     /* Otherwise, we see if one has a slurpy and the other not. A lack of
      * slurpiness makes the candidate narrower. */
 
-    if (a->max_arity != SLURPY_ARITY && b->max_arity == SLURPY_ARITY) {
+    if (a_info->max_arity != SLURPY_ARITY && b_info->max_arity == SLURPY_ARITY) {
         return 1;
     }
 
     /* Also narrower if the first needs a bind check and the second doesn't, if
      * we wouldn't deem the other one narrower than this one int terms of
      * slurpyness. Otherwise, they're tied. */
-    return !(b->max_arity != SLURPY_ARITY && a->max_arity == SLURPY_ARITY)
-        && (a->bind_check && !(b->bind_check));
+    return !(b_info->max_arity != SLURPY_ARITY && a_info->max_arity == SLURPY_ARITY)
+        && (a_info->bind_check && !(b_info->bind_check));
 }
 
 
@@ -158,6 +162,7 @@ static Rakudo_md_candidate_info** sort_candidates(PARROT_INTERP, PMC *candidates
         INTVAL                    num_params;
         INTVAL                    j;
         INTVAL                    significant_param;
+        PMC                     **constraints;
 
         /* Get information about this candidate. */
         PMC * const candidate = VTABLE_get_pmc_keyed_int(interp, candidates, i);
@@ -174,7 +179,7 @@ static Rakudo_md_candidate_info** sort_candidates(PARROT_INTERP, PMC *candidates
         /* Type information. */
         info->types         = mem_allocate_n_zeroed_typed(num_params + 1, PMC*);
         info->type_flags    = mem_allocate_n_zeroed_typed(num_params + 1, INTVAL);
-        info->constraints   = mem_allocate_n_zeroed_typed(num_params + 1, PMC*);
+        constraints         = mem_allocate_n_zeroed_typed(num_params + 1, PMC*);
         significant_param = 0;
 
         for (j = 0; j < num_params; j++) {
@@ -220,8 +225,8 @@ static Rakudo_md_candidate_info** sort_candidates(PARROT_INTERP, PMC *candidates
             else {
                 info->types[significant_param] = param->nominal_type;
             }
-            info->constraints[significant_param] = param->post_constraints;
-            if (!PMC_IS_NULL(info->constraints[significant_param]))
+            constraints[significant_param] = param->post_constraints;
+            if (!PMC_IS_NULL(constraints[significant_param]))
                 info->bind_check = 1;
             if (param->flags & SIG_ELEM_MULTI_INVOCANT)
                 info->num_types++;
@@ -241,6 +246,7 @@ static Rakudo_md_candidate_info** sort_candidates(PARROT_INTERP, PMC *candidates
         /* Add it to graph node, and initialize list of edges. */
         graph[insert_pos]        = mem_allocate_zeroed_typed(Rakudo_md_candidate_graph_node);
         graph[insert_pos]->info  = info;
+        graph[insert_pos]->constraints  = constraints;
         graph[insert_pos]->edges = mem_allocate_n_zeroed_typed(
             num_candidates, Rakudo_md_candidate_graph_node*);
 
@@ -262,7 +268,7 @@ static Rakudo_md_candidate_info** sort_candidates(PARROT_INTERP, PMC *candidates
             for (j = 0; j < num_candidates; j++) {
                 if (i == j)
                     continue;
-                if (is_narrower(interp, graph[i]->info, graph[j]->info)) {
+                if (is_narrower(interp, graph[i], graph[j])) {
                     graph[i]->edges[graph[i]->edges_out] = graph[j];
                     graph[i]->edges_out++;
                     graph[j]->edges_in++;
@@ -318,10 +324,10 @@ static Rakudo_md_candidate_info** sort_candidates(PARROT_INTERP, PMC *candidates
                 mem_sys_free(info->types);
             if (info->type_flags)
                 mem_sys_free(info->type_flags);
-            if (info->constraints)
-                mem_sys_free(info->constraints);
             mem_sys_free(info);
         }
+        if (graph[i]->constraints)
+            mem_sys_free(graph[i]->constraints);
         mem_sys_free(graph[i]->edges);
         mem_sys_free(graph[i]);
     }
diff --git a/src/binder/multidispatch.h b/src/binder/multidispatch.h
index 3338f53..e9f6552 100644
--- a/src/binder/multidispatch.h
+++ b/src/binder/multidispatch.h
@@ -37,7 +37,6 @@ typedef struct {
     PMC    *signature;     /* The signature of the sub. */
     PMC   **types;         /* Class or role type constraints for each parameter. */
     INTVAL *type_flags;    /* Definedness and native flags for each of the types. */
-    PMC   **constraints;   /* Refinement type constraints for each parameter. */
     INTVAL  num_types;     /* Number of entries in the above two arrays. */
     INTVAL  min_arity;     /* Number of required positional arguments. */
     INTVAL  max_arity;     /* Number of required and optional positional arguments. */
@@ -86,6 +85,8 @@ typedef struct {
  * in the graph that we have arrows to. */
 typedef struct candidate_graph_node {
     Rakudo_md_candidate_info     *info;
+    /* Refinement type constraints for each parameter, only used in the sort. */
+    PMC                         **constraints;
     struct candidate_graph_node **edges;
     INTVAL                        edges_in;
     INTVAL                        edges_out;
-- 
1.8.0.1

Reply via email to