[svn:parrot] r48790 - in trunk: include/parrot lib/Parrot/Pmc2c src src/interp src/pmc

plobsing at svn.parrot.org plobsing at svn.parrot.org
Sat Sep 4 20:06:03 UTC 2010


Author: plobsing
Date: Sat Sep  4 20:06:03 2010
New Revision: 48790
URL: https://trac.parrot.org/parrot/changeset/48790

Log:
[TT #1549] add NativePCCMethod PMC to replace raw NCI

Added:
   trunk/src/pmc/nativepccmethod.pmc
Modified:
   trunk/include/parrot/interpreter.h
   trunk/include/parrot/nci.h
   trunk/lib/Parrot/Pmc2c/PMCEmitter.pm
   trunk/src/interp/inter_misc.c
   trunk/src/multidispatch.c
   trunk/src/oo.c
   trunk/src/pmc/namespace.pmc

Modified: trunk/include/parrot/interpreter.h
==============================================================================
--- trunk/include/parrot/interpreter.h	Sat Sep  4 18:29:27 2010	(r48789)
+++ trunk/include/parrot/interpreter.h	Sat Sep  4 20:06:03 2010	(r48790)
@@ -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);
 
 #define ASSERT_ARGS_interpinfo __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp))
@@ -539,15 +541,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_nci_method __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+#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(proto))
-#define ASSERT_ARGS_register_raw_nci_method_in_ns __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+    , 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(name) \
+    , PARROT_ASSERT_ARG(proto))
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
 /* HEADERIZER END: src/interp/inter_misc.c */
 

Modified: trunk/include/parrot/nci.h
==============================================================================
--- trunk/include/parrot/nci.h	Sat Sep  4 18:29:27 2010	(r48789)
+++ trunk/include/parrot/nci.h	Sat Sep  4 20:06:03 2010	(r48790)
@@ -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);

Modified: trunk/lib/Parrot/Pmc2c/PMCEmitter.pm
==============================================================================
--- trunk/lib/Parrot/Pmc2c/PMCEmitter.pm	Sat Sep  4 18:29:27 2010	(r48789)
+++ trunk/lib/Parrot/Pmc2c/PMCEmitter.pm	Sat Sep  4 20:06:03 2010	(r48790)
@@ -656,11 +656,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";

Modified: trunk/src/interp/inter_misc.c
==============================================================================
--- trunk/src/interp/inter_misc.c	Sat Sep  4 18:29:27 2010	(r48789)
+++ trunk/src/interp/inter_misc.c	Sat Sep  4 20:06:03 2010	(r48790)
@@ -64,8 +64,8 @@
 
 /*
 
-=item C<void register_raw_nci_method_in_ns(PARROT_INTERP, const int type, void
-*func, STRING *name)>
+=item C<void register_native_pcc_method_in_ns(PARROT_INTERP, const int type,
+void *func, STRING *name, STRING *signature)>
 
 Create an entry in the C<nci_method_table> for the given raw NCI method
 of PMC class C<type>.
@@ -76,14 +76,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,

Modified: trunk/src/multidispatch.c
==============================================================================
--- trunk/src/multidispatch.c	Sat Sep  4 18:29:27 2010	(r48789)
+++ trunk/src/multidispatch.c	Sat Sep  4 20:06:03 2010	(r48790)
@@ -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);
     }
@@ -969,7 +979,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)) {

Modified: trunk/src/oo.c
==============================================================================
--- trunk/src/oo.c	Sat Sep  4 18:29:27 2010	(r48789)
+++ trunk/src/oo.c	Sat Sep  4 20:06:03 2010	(r48790)
@@ -120,7 +120,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";

Modified: trunk/src/pmc/namespace.pmc
==============================================================================
--- trunk/src/pmc/namespace.pmc	Sat Sep  4 18:29:27 2010	(r48789)
+++ trunk/src/pmc/namespace.pmc	Sat Sep  4 20:06:03 2010	(r48790)
@@ -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))
@@ -235,15 +235,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)
-
-    STRING * const nci_str = CONST_STRING(interp, "NCI");
+    ASSERT_ARGS(add_native_to_namespace)
 
     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);
 
@@ -433,8 +432,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);

Added: trunk/src/pmc/nativepccmethod.pmc
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ trunk/src/pmc/nativepccmethod.pmc	Sat Sep  4 20:06:03 2010	(r48790)
@@ -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<void init()>
+
+Initializes the PMC with a C<NULL> 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<void *get_pointer()>
+
+Get the pointer to the native function.
+
+=item C<void set_pointer_keyed_str(STRING *sig, void *func)>
+
+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<INTVAL defined()>
+
+=item C<INTVAL get_bool()>
+
+NULLness check.
+
+=cut
+
+*/
+
+    VTABLE INTVAL defined() {
+        return !! PARROT_NATIVEPCCMETHOD(SELF)->func;
+    }
+
+    VTABLE INTVAL get_bool() {
+        return STATICSELF.defined();
+    }
+
+/*
+
+=item C<opcode_t *invoke(void *next)>
+
+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<void mark()>
+
+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<PMC *clone()>
+
+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<docs/pdds/pdd03_calling_conventions.pod>.
+
+=cut
+
+*/
+
+/*
+ * Local variables:
+ *   c-file-style: "parrot"
+ * End:
+ * vim: expandtab shiftwidth=4:
+ */


More information about the parrot-commits mailing list