Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

[binder] Another crack at the simple nominal type check cache. Doesn'…

…t seem to cause any test regressions. Gives a minor startup win and a notable win for code that does lots of calls.
  • Loading branch information...
commit 803a4f10cd83d7b5878f4964ccd6f32db446a050 1 parent 71328bd
Jonathan Worthington authored January 08, 2011
86  src/binder/bind.c
... ...
@@ -1,6 +1,6 @@
1 1
 /*
2 2
 $Id$
3  
-Copyright (C) 2009-2010, The Perl Foundation.
  3
+Copyright (C) 2009-2011, The Perl Foundation.
4 4
 */
5 5
 
6 6
 #define PARROT_IN_EXTENSION
@@ -15,6 +15,8 @@ Copyright (C) 2009-2010, The Perl Foundation.
15 15
 static INTVAL or_id             = 0;
16 16
 static INTVAL lls_id            = 0;
17 17
 static INTVAL p6s_id            = 0;
  18
+static INTVAL p6r_id            = 0;
  19
+static INTVAL p6o_id            = 0;
18 20
 static STRING *ACCEPTS          = NULL;
19 21
 static STRING *HOW              = NULL;
20 22
 static STRING *DO_str           = NULL;
@@ -78,6 +80,8 @@ static void setup_binder_statics(PARROT_INTERP) {
78 80
     or_id  = pmc_type(interp, Parrot_str_new(interp, "ObjectRef", 0));
79 81
     lls_id = pmc_type(interp, Parrot_str_new(interp, "P6LowLevelSig", 0));
80 82
     p6s_id = pmc_type(interp, P6_SCALAR_str);
  83
+    p6r_id = pmc_type(interp, Parrot_str_new(interp, "P6role", 0));
  84
+    p6o_id = pmc_type(interp, Parrot_str_new(interp, "P6opaque", 0));
81 85
 }
82 86
 
83 87
 
@@ -260,32 +264,62 @@ Rakudo_binding_bind_one_param(PARROT_INTERP, PMC *lexpad, llsig_element *sig_inf
260 264
                               PMC *value, INTVAL no_nom_type_check, STRING **error) {
261 265
     /* If we need to do a type check, do one. */
262 266
     if (!no_nom_type_check) {
263  
-        PMC * const type_obj   = sig_info->nominal_type;
264  
-        PMC * accepts_meth     = VTABLE_find_method(interp, type_obj, ACCEPTS);
265  
-        PMC * result           = PMCNULL;
266  
-        Parrot_ext_call(interp, accepts_meth, "PiP->P", type_obj, value, &result);
267  
-        if (!VTABLE_get_bool(interp, result)) {
268  
-            /* Type check failed. However, for language inter-op, we do some
269  
-             * extra checks if the type is just Positional, Associative, or
270  
-             * Callable and the thingy we have matches those enough. */
271  
-            /* XXX TODO: Implement language interop checks. */
272  
-            if (error) {
273  
-                STRING * const perl = PERL_str;
274  
-                PMC    * perl_meth  = VTABLE_find_method(interp, type_obj, perl);
275  
-                PMC    * how_meth   = VTABLE_find_method(interp, value, HOW);
276  
-                STRING * expected, * got;
277  
-                PMC    * value_how, * value_type;
278  
-                Parrot_ext_call(interp, perl_meth, "Pi->S", type_obj, &expected);
279  
-                Parrot_ext_call(interp, how_meth, "Pi->P", value, &value_how);
280  
-                value_type = VTABLE_get_attr_str(interp, value_how, SHORTNAME_str);
281  
-                got        = VTABLE_get_string(interp, value_type);
282  
-                *error = Parrot_sprintf_c(interp, "Nominal type check failed for parameter '%S'; expected %S but got %S instead",
283  
-                            sig_info->variable_name, expected, got);
  267
+        /* See if we get a hit in the type cache. */
  268
+        INTVAL cache_matched = 0;
  269
+        INTVAL value_type = VTABLE_type(interp, value);
  270
+        if (value_type != 0) {
  271
+            INTVAL i;
  272
+            for (i = 0; i < NOM_TYPE_CACHE_SIZE; i++) {
  273
+                if (sig_info->nom_type_cache[i] == value_type)
  274
+                {
  275
+                    cache_matched = 1;
  276
+                    break;
  277
+                }
  278
+            }
  279
+        }
  280
+        
  281
+        /* If not, do the check. */
  282
+        if (!cache_matched) {
  283
+            PMC * const type_obj   = sig_info->nominal_type;
  284
+            PMC * accepts_meth     = VTABLE_find_method(interp, type_obj, ACCEPTS);
  285
+            PMC * result           = PMCNULL;
  286
+            Parrot_ext_call(interp, accepts_meth, "PiP->P", type_obj, value, &result);
  287
+            if (VTABLE_get_bool(interp, result)) {
  288
+                /* Cache if possible. */
  289
+                if (value_type != 0 && value_type != p6r_id && value_type != p6o_id) {
  290
+                    INTVAL i;
  291
+                    for (i = 0; i < NOM_TYPE_CACHE_SIZE; i++) {
  292
+                        if (sig_info->nom_type_cache[i] == 0)
  293
+                        {
  294
+                            sig_info->nom_type_cache[i] = value_type;
  295
+                            break;
  296
+                        }
  297
+                    }
  298
+                }
  299
+            }
  300
+            else {
  301
+                /* Type check failed. However, for language inter-op, we do some
  302
+                 * extra checks if the type is just Positional, Associative, or
  303
+                 * Callable and the thingy we have matches those enough. */
  304
+                /* XXX TODO: Implement language interop checks. */
  305
+                if (error) {
  306
+                    STRING * const perl = PERL_str;
  307
+                    PMC    * perl_meth  = VTABLE_find_method(interp, type_obj, perl);
  308
+                    PMC    * how_meth   = VTABLE_find_method(interp, value, HOW);
  309
+                    STRING * expected, * got;
  310
+                    PMC    * value_how, * value_type;
  311
+                    Parrot_ext_call(interp, perl_meth, "Pi->S", type_obj, &expected);
  312
+                    Parrot_ext_call(interp, how_meth, "Pi->P", value, &value_how);
  313
+                    value_type = VTABLE_get_attr_str(interp, value_how, SHORTNAME_str);
  314
+                    got        = VTABLE_get_string(interp, value_type);
  315
+                    *error = Parrot_sprintf_c(interp, "Nominal type check failed for parameter '%S'; expected %S but got %S instead",
  316
+                                sig_info->variable_name, expected, got);
  317
+                }
  318
+                if (VTABLE_isa(interp, value, JUNCTION_str))
  319
+                    return BIND_RESULT_JUNCTION;
  320
+                else
  321
+                    return BIND_RESULT_FAIL;
284 322
             }
285  
-            if (VTABLE_isa(interp, value, JUNCTION_str))
286  
-                return BIND_RESULT_JUNCTION;
287  
-            else
288  
-                return BIND_RESULT_FAIL;
289 323
         }
290 324
     }
291 325
 
2  src/binder/bind.h
@@ -18,6 +18,7 @@
18 18
 #define SIG_ELEM_DEFAULT_FROM_OUTER 16384
19 19
 #define SIG_ELEM_IS_CAPTURE         32768
20 20
 
  21
+#define NOM_TYPE_CACHE_SIZE 4
21 22
 
22 23
 /* Data structure to describe a single element in the signature. */
23 24
 typedef struct llsig_element {
@@ -26,6 +27,7 @@ typedef struct llsig_element {
26 27
     PMC    *type_captures;    /* Name(s) that we bind the type of a parameter to. */
27 28
     INTVAL flags;             /* Various flags about the parameter. */
28 29
     PMC    *nominal_type;     /* The nominal type of the parameter. */
  30
+    INTVAL nom_type_cache[NOM_TYPE_CACHE_SIZE]; /* IDs of nominal types that match. */
29 31
     PMC    *post_constraints; /* Array of any extra constraints; we will do a
30 32
                                * smart-match against each of them. For now, we
31 33
                                * always expect an array of blocks. */

0 notes on commit 803a4f1

Please sign in to comment.
Something went wrong with that request. Please try again.