Skip to content

Commit

Permalink
[PMC] Delayed NCI thunk initialization until absolutely necessary. This
Browse files Browse the repository at this point in the history
improves Parrot startup time by 2.859%, thanks to a wealth of (usually unused)
PMC MMD NCI registrations.

git-svn-id: https://svn.parrot.org/parrot/trunk@40680 d31e2699-5ff4-0310-a27c-f18f2fbe73fe
  • Loading branch information
chromatic committed Aug 20, 2009
1 parent d9b1907 commit 8832378
Showing 1 changed file with 57 additions and 35 deletions.
92 changes: 57 additions & 35 deletions src/pmc/nci.pmc
Original file line number Original file line Diff line number Diff line change
@@ -1,5 +1,5 @@
/* /*
Copyright (C) 2001-2008, Parrot Foundation. Copyright (C) 2001-2009, Parrot Foundation.
$Id$ $Id$


=head1 NAME =head1 NAME
Expand Down Expand Up @@ -100,6 +100,29 @@ void pcc_params(PARROT_INTERP, STRING *sig, Parrot_NCI_attributes * const nci_in
mem_sys_free(param_sig); mem_sys_free(param_sig);
} }


/* actually build the NCI thunk */
static nci_sub_t build_func(PARROT_INTERP, PMC *, Parrot_NCI_attributes *);

static
nci_sub_t build_func(PARROT_INTERP, PMC *pmc, Parrot_NCI_attributes *nci_info)
{
nci_sub_t func;
STRING *key = nci_info->signature;
size_t key_length = Parrot_str_byte_length(interp, key);
int jitted = 0;

pcc_params(interp, key, nci_info, key_length);

/* Arity is length of that string minus one (the return type). */
nci_info->arity = key_length - 1;

/* Build call function. */
func = nci_info->func = (PMC *)(build_call_func(interp, pmc, key, &jitted));
nci_info->jitted = jitted;

return func;
}



pmclass NCI need_ext auto_attrs { pmclass NCI need_ext auto_attrs {
ATTR STRING *signature; /* The signature. */ ATTR STRING *signature; /* The signature. */
Expand Down Expand Up @@ -181,30 +204,20 @@ Sets the specified function pointer and signature (C<*key>).


VTABLE void set_pointer_keyed_str(STRING *key, void *func) { VTABLE void set_pointer_keyed_str(STRING *key, void *func) {
Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF); Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF);
int jitted = 0;
size_t key_length = Parrot_str_byte_length(interp, key);


/* Store the original function and signature. */ /* Store the original function and signature. */
SET_ATTR_orig_func(INTERP, SELF, func); SET_ATTR_orig_func(INTERP, SELF, func);


/* ensure that the STRING signature is constant */ /* ensure that the STRING signature is constant */
if (!PObj_constant_TEST(key)) { if (!PObj_constant_TEST(key)) {
char * const key_c = Parrot_str_to_cstring(INTERP, key); char * const key_c = Parrot_str_to_cstring(INTERP, key);
key = string_make(interp, key_c, key_length, size_t key_length = Parrot_str_byte_length(interp, key);
NULL, PObj_constant_FLAG); key = string_make(interp, key_c, key_length,
NULL, PObj_constant_FLAG);
Parrot_str_free_cstring(key_c); Parrot_str_free_cstring(key_c);
} }


nci_info->signature = key; nci_info->signature = key;
pcc_params(INTERP, key, nci_info, key_length);

/* Arity is length of that string minus one (the return type). */
nci_info->arity = key_length - 1;

/* Build call function. */
nci_info->func = (PMC *)(build_call_func(INTERP, SELF,
key, &jitted));
nci_info->jitted = jitted;
} }


/* /*
Expand Down Expand Up @@ -273,23 +286,21 @@ Returns whether the NCI is defined.


VTABLE INTVAL defined() { VTABLE INTVAL defined() {
Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF); Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF);
return nci_info->func != NULL; return nci_info->orig_func != NULL;
} }


/* /*


=item C<opcode_t *invoke(void *next)> =item C<opcode_t *invoke(void *next)>


Calls the associated C function, returning C<*next>. If Calls the associated C function, returning C<*next>. If the invocant is a
the invocant is a class, the PMC arguments are class, the PMC arguments are shifted down.
shifted down.


=cut =cut


*/ */


VTABLE opcode_t *invoke(void *next) { VTABLE opcode_t *invoke(void *next) {

Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF); Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF);
nci_sub_t func; nci_sub_t func;
void *orig_func; void *orig_func;
Expand All @@ -300,12 +311,17 @@ shifted down.
? (nci_sub_t) D2FPTR(orig_func) ? (nci_sub_t) D2FPTR(orig_func)
: (nci_sub_t) D2FPTR(nci_info->func); : (nci_sub_t) D2FPTR(nci_info->func);


if (!func) if (!func) {
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION, /* build the thunk only when necessary */
"attempt to call NULL function"); func = build_func(interp, SELF, nci_info);


if (nci_info->jitted) { if (!func)
Parrot_ex_throw_from_c_args(INTERP, NULL,
EXCEPTION_INVALID_OPERATION,
"attempt to call NULL function");
}


if (nci_info->jitted) {
nci_jit_sub_t jit_func = (nci_jit_sub_t) D2FPTR(nci_info->func); nci_jit_sub_t jit_func = (nci_jit_sub_t) D2FPTR(nci_info->func);


/* Parrot_eprintf(interp, "JITTED %S\n", nci_info->signature); */ /* Parrot_eprintf(interp, "JITTED %S\n", nci_info->signature); */
Expand All @@ -329,8 +345,8 @@ shifted down.
* return continuation here, which gets rid of this frame * return continuation here, which gets rid of this frame
* and returns the real return address * and returns the real return address
*/ */
if (cont && cont != NEED_CONTINUATION && if (cont && cont != NEED_CONTINUATION
(PObj_get_FLAGS(cont) & SUB_FLAG_TAILCALL)) { && (PObj_get_FLAGS(cont) & SUB_FLAG_TAILCALL)) {
cont = CONTEXT(interp)->current_cont; cont = CONTEXT(interp)->current_cont;
next = VTABLE_invoke(INTERP, cont, next); next = VTABLE_invoke(INTERP, cont, next);
} }
Expand All @@ -350,6 +366,8 @@ Returns the function pointer as an integer.


VTABLE INTVAL get_integer() { VTABLE INTVAL get_integer() {
Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF); Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF);
if (!nci_info->func)
build_func(INTERP, SELF, nci_info);
return (INTVAL)nci_info->func; return (INTVAL)nci_info->func;
} }


Expand All @@ -365,7 +383,7 @@ Returns the boolean value of the pointer.


VTABLE INTVAL get_bool() { VTABLE INTVAL get_bool() {
Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF); Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF);
return (0 != (INTVAL)nci_info->func); return (0 != (INTVAL)nci_info->orig_func);
} }


/* /*
Expand All @@ -381,14 +399,18 @@ Return the arity of the NCI (the number of arguments).
Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF); Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF);
INTVAL arity = 0; INTVAL arity = 0;


if (nci_info && nci_info->func) if (nci_info) {
arity = nci_info->arity; if (!nci_info->func)
else build_func(INTERP, SELF, nci_info);
Parrot_ex_throw_from_c_args(INTERP, NULL, if (nci_info->func) {
EXCEPTION_INVALID_OPERATION, arity = nci_info->arity;
"You cannot get the arity of an undefined NCI."); RETURN(INTVAL arity);
}
}


RETURN(INTVAL arity); Parrot_ex_throw_from_c_args(INTERP, NULL,
EXCEPTION_INVALID_OPERATION,
"You cannot get the arity of an undefined NCI.");
} }
} }


Expand Down

0 comments on commit 8832378

Please sign in to comment.