[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