Index: src/multidispatch.c =================================================================== --- src/multidispatch.c (revision 46694) +++ src/multidispatch.c (working copy) @@ -43,6 +43,7 @@ #include "parrot/oplib/ops.h" #include "multidispatch.str" #include "pmc/pmc_nci.h" +#include "pmc/pmc_nativepccmethod.h" #include "pmc/pmc_sub.h" #include "pmc/pmc_callcontext.h" @@ -590,8 +591,17 @@ Parrot_Sub_attributes *sub; INTVAL args, dist, i, j, n, m; - /* has to be a builtin multi method */ - if (pmc->vtable->base_type == enum_class_NCI) { + if (pmc->vtable->base_type == enum_class_NativePCCMethod) { + GETATTR_NativePCCMethod_mmd_multi_sig(interp, pmc, multi_sig); + if (PMC_IS_NULL(multi_sig)) { + STRING *long_sig; + + GETATTR_NativePCCMethod_mmd_long_signature(interp, pmc, long_sig); + multi_sig = mmd_build_type_tuple_from_long_sig(interp, long_sig); + SETATTR_NativePCCMethod_mmd_multi_sig(interp, pmc, multi_sig); + } + } + else if (pmc->vtable->base_type == enum_class_NCI) { GETATTR_NCI_multi_sig(interp, pmc, multi_sig); if (PMC_IS_NULL(multi_sig)) { STRING *long_sig; @@ -602,10 +612,10 @@ } } else { - /* not a multi; no distance */ PMC_get_sub(interp, pmc, sub); + if (!sub->multi_signature) - return 0; + return 0; /* not a multi; no distance */ multi_sig = Parrot_mmd_get_cached_multi_sig(interp, pmc); } @@ -970,7 +980,10 @@ /* Attach a type tuple array to the sub for multi dispatch */ PMC *multi_sig = mmd_build_type_tuple_from_type_list(interp, type_list); - if (sub_obj->vtable->base_type == enum_class_NCI) { + if (sub_obj->vtable->base_type == enum_class_NativePCCMethod) { + SETATTR_NativePCCMethod_mmd_multi_sig(interp, sub_obj, multi_sig); + } + else if (sub_obj->vtable->base_type == enum_class_NCI) { SETATTR_NCI_multi_sig(interp, sub_obj, multi_sig); } else if (VTABLE_isa(interp, sub_obj, sub_str) Index: src/oo.c =================================================================== --- src/oo.c (revision 46694) +++ src/oo.c (working copy) @@ -998,7 +998,9 @@ class_name = _class->vtable->whoami; if (sub) { - if (sub->vtable->base_type == enum_class_NCI) + if (sub->vtable->base_type == enum_class_NativePCCMethod) + result = "NativePCCMethod"; + else if (sub->vtable->base_type == enum_class_NCI) result = "NCI"; else result = "Sub"; Index: src/pmc/nativepccmethod.pmc =================================================================== --- src/pmc/nativepccmethod.pmc (revision 0) +++ src/pmc/nativepccmethod.pmc (revision 0) @@ -0,0 +1,198 @@ +/* +Copyright (C) 2010, Parrot Foundation. +$Id$ + +=head1 NAME + +src/pmc/nativepccmethod.pmc - Native PCC Method PMC + +=head1 DESCRIPTION + +Container for native functions that handle PCC on their own. + +=head2 Methods + +=over 4 + +=cut + +*/ + +/* HEADERIZER HFILE: none */ + +pmclass NativePCCMethod auto_attrs { + ATTR STRING *signature; + ATTR void *func; + + /* MMD fields */ + ATTR STRING *mmd_long_signature; + ATTR PMC *mmd_multi_sig; + +/* + +=item C + +Initializes the PMC with a C function pointer. + +=cut + +*/ + + VTABLE void init() { + Parrot_NativePCCMethod_attributes *attrs = PARROT_NATIVEPCCMETHOD(SELF); + + attrs->func = NULL; + attrs->signature = STRINGNULL; + attrs->mmd_long_signature = STRINGNULL; + attrs->mmd_multi_sig = PMCNULL; + + PObj_custom_mark_SET(SELF); + } + +/* + +=item C + +Get the pointer to the native function. + +=item C + +Set the pointer to the native function and the PCC signature. + +=cut + +*/ + + + VTABLE void *get_pointer() { + return PARROT_NATIVEPCCMETHOD(SELF)->func; + } + + VTABLE void set_pointer_keyed_str(STRING *sig, void *func) { + PARROT_NATIVEPCCMETHOD(SELF)->signature = sig; + PARROT_NATIVEPCCMETHOD(SELF)->func = func; + } + +/* + +=item C + +=item C + +NULLness check. + +=cut + +*/ + + VTABLE INTVAL defined() { + return !! PARROT_NATIVEPCCMETHOD(SELF)->func; + } + + VTABLE INTVAL get_bool() { + return STATICSELF.defined(); + } + +/* + +=item C + +Call the function pointer. + +=cut + +*/ + + VTABLE opcode_t *invoke(void *next) { + void *func; + native_pcc_method_t fptr; + + GET_ATTR_func(INTERP, SELF, func); + if (!func) + Parrot_ex_throw_from_c_args(INTERP, NULL, + EXCEPTION_INVALID_OPERATION, + "attempt to call NULL native function"); + + fptr = D2FPTR(func); + fptr(INTERP); + + /* + * If this function was tailcalled, the return result + * is already passed back to the caller of this frame. + * We therefore invoke the return continuation here, + * which gets rid of this frame and returns the real + * return address. + */ + { + PMC *cont = INTERP->current_cont; + + if (cont && cont != NEED_CONTINUATION + && (PObj_get_FLAGS(cont) & SUB_FLAG_TAILCALL)) { + cont = Parrot_pcc_get_continuation(interp, CURRENT_CONTEXT(interp)); + next = VTABLE_invoke(INTERP, cont, next); + } + } + + return (opcode_t *)next; + } + +/* + +=item C + +Mark contained elements for GC. + +=cut + +*/ + + VTABLE void mark() { + Parrot_NativePCCMethod_attributes *attrs = PARROT_NATIVEPCCMETHOD(SELF); + + Parrot_gc_mark_STRING_alive(interp, attrs->signature); + Parrot_gc_mark_STRING_alive(interp, attrs->mmd_long_signature); + Parrot_gc_mark_PMC_alive(interp, attrs->mmd_multi_sig); + } + +/* + +=item C + +Create a clone of this PMC. + +=cut + +*/ + + VTABLE PMC *clone() { + PMC *ret = Parrot_pmc_new(INTERP, SELF->vtable->base_type); + Parrot_NativePCCMethod_attributes *self_attrs = PARROT_NATIVEPCCMETHOD(SELF); + Parrot_NativePCCMethod_attributes *ret_attrs = PARROT_NATIVEPCCMETHOD(ret); + + ret_attrs->func = self_attrs->func; + ret_attrs->signature = self_attrs->signature; + ret_attrs->mmd_long_signature = self_attrs->mmd_long_signature; + ret_attrs->mmd_multi_sig = self_attrs->mmd_multi_sig; + + return ret; + } +} + +/* + +=back + +=head1 SEE ALSO + +F. + +=cut + +*/ + +/* + * Local variables: + * c-file-style: "parrot" + * End: + * vim: expandtab shiftwidth=4: + */ Index: src/pmc/namespace.pmc =================================================================== --- src/pmc/namespace.pmc (revision 46694) +++ src/pmc/namespace.pmc (working copy) @@ -32,7 +32,7 @@ __attribute__nonnull__(2) __attribute__nonnull__(3); -static void add_nci_to_namespace(PARROT_INTERP, +static void add_native_to_namespace(PARROT_INTERP, ARGIN(PMC *SELF), ARGIN(STRING *key), ARGIN_NULLOK(PMC *value)) @@ -76,7 +76,7 @@ PARROT_ASSERT_ARG(interp) \ , PARROT_ASSERT_ARG(SELF) \ , PARROT_ASSERT_ARG(key)) -#define ASSERT_ARGS_add_nci_to_namespace __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ +#define ASSERT_ARGS_add_native_to_namespace __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ PARROT_ASSERT_ARG(interp) \ , PARROT_ASSERT_ARG(SELF) \ , PARROT_ASSERT_ARG(key)) @@ -199,15 +199,14 @@ } static void -add_nci_to_namespace(PARROT_INTERP, ARGIN(PMC *SELF), ARGIN(STRING *key), +add_native_to_namespace(PARROT_INTERP, ARGIN(PMC *SELF), ARGIN(STRING *key), ARGIN_NULLOK(PMC *value)) { - ASSERT_ARGS(add_nci_to_namespace) + ASSERT_ARGS(add_native_to_namespace) - STRING * const nci_str = CONST_STRING(interp, "NCI"); - if (!PMC_IS_NULL(value) - && VTABLE_isa(interp, value, nci_str)) { + && (value->vtable->base_type == enum_class_NativePCCMethod || + value->vtable->base_type == enum_class_NCI)) { Parrot_NameSpace_attributes * const nsinfo = PARROT_NAMESPACE(SELF); PMC * const classobj = VTABLE_get_class(interp, SELF); @@ -388,8 +387,8 @@ if (maybe_add_sub_to_namespace(INTERP, SELF, key, value)) return; - /* If it's an NCI method */ - add_nci_to_namespace(INTERP, SELF, key, value); + /* If it's an native method */ + add_native_to_namespace(INTERP, SELF, key, value); /* If it's a multi-sub and the first in this NS... */ add_multi_to_namespace(INTERP, SELF, key, value); Index: src/interp/inter_misc.c =================================================================== --- src/interp/inter_misc.c (revision 46694) +++ src/interp/inter_misc.c (working copy) @@ -68,8 +68,8 @@ /* -=item C +=item C Create an entry in the C for the given raw NCI method of PMC class C. @@ -80,14 +80,14 @@ PARROT_EXPORT void -register_raw_nci_method_in_ns(PARROT_INTERP, const int type, ARGIN(void *func), - ARGIN(STRING *name)) +register_native_pcc_method_in_ns(PARROT_INTERP, const int type, ARGIN(void *func), + ARGIN(STRING *name), ARGIN(STRING *signature)) { - ASSERT_ARGS(register_raw_nci_method_in_ns) - PMC * const method = Parrot_pmc_new(interp, enum_class_NCI); + ASSERT_ARGS(register_native_pcc_method_in_ns) + PMC * method = Parrot_pmc_new(interp, enum_class_NativePCCMethod); /* setup call func */ - VTABLE_set_pointer(interp, method, func); + VTABLE_set_pointer_keyed_str(interp, method, signature, func); /* insert it into namespace */ VTABLE_set_pmc_keyed_str(interp, interp->vtables[type]->_namespace, Index: lib/Parrot/Pmc2c/PMCEmitter.pm =================================================================== --- lib/Parrot/Pmc2c/PMCEmitter.pm (revision 46694) +++ lib/Parrot/Pmc2c/PMCEmitter.pm (working copy) @@ -666,11 +666,18 @@ next unless $method->type eq Parrot::Pmc2c::Method::NON_VTABLE; #these differ for METHODs - my $method_name = $method->name; - my $symbol_name = $method->symbol; + my $method_name = $method->name; + my $symbol_name = $method->symbol; + my ($pcc_signature) = $method->pcc_signature; $cout .= <<"EOC"; - register_raw_nci_method_in_ns(interp, entry, F2DPTR(Parrot_${classname}_${method_name}), CONST_STRING_GEN(interp, "$symbol_name")); + { + STRING *method_name = CONST_STRING_GEN(interp, "$symbol_name"); + STRING *signature = CONST_STRING_GEN(interp, "$pcc_signature"); + register_native_pcc_method_in_ns(interp, entry, + F2DPTR(Parrot_${classname}_${method_name}), + method_name, signature); + } EOC if ( $method->{attrs}{write} ) { $cout .= <<"EOC"; Index: include/parrot/interpreter.h =================================================================== --- include/parrot/interpreter.h (revision 46694) +++ include/parrot/interpreter.h (working copy) @@ -503,24 +503,26 @@ __attribute__nonnull__(3); PARROT_EXPORT -void register_nci_method(PARROT_INTERP, +void register_native_pcc_method_in_ns(PARROT_INTERP, const int type, ARGIN(void *func), - ARGIN(const char *name), - ARGIN(const char *proto)) + ARGIN(STRING *name), + ARGIN(STRING *signature)) __attribute__nonnull__(1) __attribute__nonnull__(3) __attribute__nonnull__(4) __attribute__nonnull__(5); PARROT_EXPORT -void register_raw_nci_method_in_ns(PARROT_INTERP, +void register_nci_method(PARROT_INTERP, const int type, ARGIN(void *func), - ARGIN(STRING *name)) + ARGIN(const char *name), + ARGIN(const char *proto)) __attribute__nonnull__(1) __attribute__nonnull__(3) - __attribute__nonnull__(4); + __attribute__nonnull__(4) + __attribute__nonnull__(5); PARROT_WARN_UNUSED_RESULT INTVAL sysinfo_i(SHIM_INTERP, INTVAL info_wanted); @@ -547,15 +549,17 @@ #define ASSERT_ARGS_Parrot_mark_method_writes __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ PARROT_ASSERT_ARG(interp) \ , PARROT_ASSERT_ARG(name)) +#define ASSERT_ARGS_register_native_pcc_method_in_ns \ + __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ + PARROT_ASSERT_ARG(interp) \ + , PARROT_ASSERT_ARG(func) \ + , PARROT_ASSERT_ARG(name) \ + , PARROT_ASSERT_ARG(signature)) #define ASSERT_ARGS_register_nci_method __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ PARROT_ASSERT_ARG(interp) \ , PARROT_ASSERT_ARG(func) \ , PARROT_ASSERT_ARG(name) \ , PARROT_ASSERT_ARG(proto)) -#define ASSERT_ARGS_register_raw_nci_method_in_ns __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ - PARROT_ASSERT_ARG(interp) \ - , PARROT_ASSERT_ARG(func) \ - , PARROT_ASSERT_ARG(name)) #define ASSERT_ARGS_sysinfo_i __attribute__unused__ int _ASSERT_ARGS_CHECK = (0) #define ASSERT_ARGS_sysinfo_s __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ PARROT_ASSERT_ARG(interp)) Index: include/parrot/nci.h =================================================================== --- include/parrot/nci.h (revision 46694) +++ include/parrot/nci.h (working copy) @@ -17,6 +17,7 @@ typedef PMC *(*nci_fb_func_t)(PARROT_INTERP, PMC *user_data, STRING *signature); typedef void (*nci_thunk_t)(PARROT_INTERP, PMC *, PMC *); +typedef void (*native_pcc_method_t)(PARROT_INTERP); void Parrot_nci_load_core_thunks(PARROT_INTERP); void Parrot_nci_load_extra_thunks(PARROT_INTERP);