Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

[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
@jnthn jnthn authored
Showing with 62 additions and 26 deletions.
  1. +60 −26 src/binder/bind.c
  2. +2 −0  src/binder/bind.h
View
86 src/binder/bind.c
@@ -1,6 +1,6 @@
/*
$Id$
-Copyright (C) 2009-2010, The Perl Foundation.
+Copyright (C) 2009-2011, The Perl Foundation.
*/
#define PARROT_IN_EXTENSION
@@ -15,6 +15,8 @@ Copyright (C) 2009-2010, The Perl Foundation.
static INTVAL or_id = 0;
static INTVAL lls_id = 0;
static INTVAL p6s_id = 0;
+static INTVAL p6r_id = 0;
+static INTVAL p6o_id = 0;
static STRING *ACCEPTS = NULL;
static STRING *HOW = NULL;
static STRING *DO_str = NULL;
@@ -78,6 +80,8 @@ static void setup_binder_statics(PARROT_INTERP) {
or_id = pmc_type(interp, Parrot_str_new(interp, "ObjectRef", 0));
lls_id = pmc_type(interp, Parrot_str_new(interp, "P6LowLevelSig", 0));
p6s_id = pmc_type(interp, P6_SCALAR_str);
+ p6r_id = pmc_type(interp, Parrot_str_new(interp, "P6role", 0));
+ p6o_id = pmc_type(interp, Parrot_str_new(interp, "P6opaque", 0));
}
@@ -260,32 +264,62 @@ Rakudo_binding_bind_one_param(PARROT_INTERP, PMC *lexpad, llsig_element *sig_inf
PMC *value, INTVAL no_nom_type_check, STRING **error) {
/* If we need to do a type check, do one. */
if (!no_nom_type_check) {
- PMC * const type_obj = sig_info->nominal_type;
- PMC * accepts_meth = VTABLE_find_method(interp, type_obj, ACCEPTS);
- PMC * result = PMCNULL;
- Parrot_ext_call(interp, accepts_meth, "PiP->P", type_obj, value, &result);
- if (!VTABLE_get_bool(interp, result)) {
- /* Type check failed. However, for language inter-op, we do some
- * extra checks if the type is just Positional, Associative, or
- * Callable and the thingy we have matches those enough. */
- /* XXX TODO: Implement language interop checks. */
- if (error) {
- STRING * const perl = PERL_str;
- PMC * perl_meth = VTABLE_find_method(interp, type_obj, perl);
- PMC * how_meth = VTABLE_find_method(interp, value, HOW);
- STRING * expected, * got;
- PMC * value_how, * value_type;
- Parrot_ext_call(interp, perl_meth, "Pi->S", type_obj, &expected);
- Parrot_ext_call(interp, how_meth, "Pi->P", value, &value_how);
- value_type = VTABLE_get_attr_str(interp, value_how, SHORTNAME_str);
- got = VTABLE_get_string(interp, value_type);
- *error = Parrot_sprintf_c(interp, "Nominal type check failed for parameter '%S'; expected %S but got %S instead",
- sig_info->variable_name, expected, got);
+ /* See if we get a hit in the type cache. */
+ INTVAL cache_matched = 0;
+ INTVAL value_type = VTABLE_type(interp, value);
+ if (value_type != 0) {
+ INTVAL i;
+ for (i = 0; i < NOM_TYPE_CACHE_SIZE; i++) {
+ if (sig_info->nom_type_cache[i] == value_type)
+ {
+ cache_matched = 1;
+ break;
+ }
+ }
+ }
+
+ /* If not, do the check. */
+ if (!cache_matched) {
+ PMC * const type_obj = sig_info->nominal_type;
+ PMC * accepts_meth = VTABLE_find_method(interp, type_obj, ACCEPTS);
+ PMC * result = PMCNULL;
+ Parrot_ext_call(interp, accepts_meth, "PiP->P", type_obj, value, &result);
+ if (VTABLE_get_bool(interp, result)) {
+ /* Cache if possible. */
+ if (value_type != 0 && value_type != p6r_id && value_type != p6o_id) {
+ INTVAL i;
+ for (i = 0; i < NOM_TYPE_CACHE_SIZE; i++) {
+ if (sig_info->nom_type_cache[i] == 0)
+ {
+ sig_info->nom_type_cache[i] = value_type;
+ break;
+ }
+ }
+ }
+ }
+ else {
+ /* Type check failed. However, for language inter-op, we do some
+ * extra checks if the type is just Positional, Associative, or
+ * Callable and the thingy we have matches those enough. */
+ /* XXX TODO: Implement language interop checks. */
+ if (error) {
+ STRING * const perl = PERL_str;
+ PMC * perl_meth = VTABLE_find_method(interp, type_obj, perl);
+ PMC * how_meth = VTABLE_find_method(interp, value, HOW);
+ STRING * expected, * got;
+ PMC * value_how, * value_type;
+ Parrot_ext_call(interp, perl_meth, "Pi->S", type_obj, &expected);
+ Parrot_ext_call(interp, how_meth, "Pi->P", value, &value_how);
+ value_type = VTABLE_get_attr_str(interp, value_how, SHORTNAME_str);
+ got = VTABLE_get_string(interp, value_type);
+ *error = Parrot_sprintf_c(interp, "Nominal type check failed for parameter '%S'; expected %S but got %S instead",
+ sig_info->variable_name, expected, got);
+ }
+ if (VTABLE_isa(interp, value, JUNCTION_str))
+ return BIND_RESULT_JUNCTION;
+ else
+ return BIND_RESULT_FAIL;
}
- if (VTABLE_isa(interp, value, JUNCTION_str))
- return BIND_RESULT_JUNCTION;
- else
- return BIND_RESULT_FAIL;
}
}
View
2  src/binder/bind.h
@@ -18,6 +18,7 @@
#define SIG_ELEM_DEFAULT_FROM_OUTER 16384
#define SIG_ELEM_IS_CAPTURE 32768
+#define NOM_TYPE_CACHE_SIZE 4
/* Data structure to describe a single element in the signature. */
typedef struct llsig_element {
@@ -26,6 +27,7 @@ typedef struct llsig_element {
PMC *type_captures; /* Name(s) that we bind the type of a parameter to. */
INTVAL flags; /* Various flags about the parameter. */
PMC *nominal_type; /* The nominal type of the parameter. */
+ INTVAL nom_type_cache[NOM_TYPE_CACHE_SIZE]; /* IDs of nominal types that match. */
PMC *post_constraints; /* Array of any extra constraints; we will do a
* smart-match against each of them. For now, we
* always expect an array of blocks. */
Please sign in to comment.
Something went wrong with that request. Please try again.