Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
tag: RELEASE_0_4_8
Fetching contributors…

Cannot retrieve contributors at this time

231 lines (148 sloc) 4.016 kb
/*
Copyright (C) 2001-2003, The Perl Foundation.
$Id$
=head1 NAME
src/pmc/nci.pmc - Native Call Interface
=head1 DESCRIPTION
The vtable functions for the native C call functions.
Invoking an NCI function changes some registers according to PDD 3.
The caller has to preserve registers if needed.
=head2 Methods
=over 4
=cut
*/
#include "parrot/parrot.h"
pmclass NCI need_ext {
/*
=item C<METHOD PMC* get_multisig()>
Return the MMD signature PMC, if any or a Null PMC.
=cut
*/
METHOD PMC* get_multisig() {
return PMC_pmc_val(SELF) ? PMC_pmc_val(SELF) : PMCNULL;
}
/*
=item C<METHOD PMC* set_raw_nci_ptr(void *func)>
Sets the specified function pointer and raw flag.
=cut
*/
METHOD void make_raw_nci(void *func) {
PMC_struct_val(SELF) = func;
PObj_flag_SET(private2, SELF);
}
/*
=item C<void init()>
Initializes the NCI with a C<NULL> function pointer.
=cut
*/
void init() {
PMC_struct_val(SELF) = NULL;
PMC_pmc_val(SELF) = NULL;
PObj_flag_CLEAR(private2, SELF);
}
/*
=item C<void set_pointer_keyed_str(STRING *key, void *func)>
Sets the specified function pointer and signature (C<*key>).
=cut
*/
void set_pointer_keyed_str(STRING *key, void *func) {
/* key = signature */
PMC_struct_val(SELF) = func;
PMC_data(SELF) = build_call_func(INTERP, SELF, key);
}
/*
=item C<void destroy()>
Destroys the NCI, freeing any allocated memory.
=cut
*/
void destroy() {
if (PMC_data(SELF))
mem_free_executable(PMC_data(SELF));
}
/*
=item C<PMC *clone()>
Creates and returns a clone of the NCI.
=cut
*/
PMC* clone() {
PMC* ret = pmc_new_noinit(INTERP, SELF->vtable->base_type);
PMC_struct_val(ret) = PMC_struct_val(SELF);
PMC_pmc_val(ret) = NULL;
/* FIXME if data is malloced (JIT/i386!) then we need
* the length of data here, to memcpy it
* ManagedStruct or Buffer?
*/
PMC_data(ret) = PMC_data(SELF);
PObj_get_FLAGS(ret) |= (PObj_get_FLAGS(SELF) & 0x3);
return ret;
}
/*
=item C<INTVAL defined()>
Returns whether the NCI is defined.
=cut
*/
INTVAL defined() {
return PMC_data(SELF) != NULL;
}
/*
=item C<void *invoke(void *next)>
Calls the associated C function, returning C<*next>. If
the invocant is a class, the PMC arguments are
shifted down.
=cut
*/
void* invoke(void * next) {
typedef INTVAL(*nci_sub_t)(Interp * , PMC * );
nci_sub_t func = PObj_flag_TEST(private2, SELF) ? PMC_struct_val(SELF)
: (nci_sub_t)D2FPTR(PMC_data(SELF));
PMC *cont;
if (!func)
real_exception(INTERP, NULL, INVALID_OPERATION,
"attempt to call NULL function");
func(INTERP, SELF);
cont = INTERP->current_cont;
/*
* If the NCI function was tailcalled, the return result
* is already passed back to the caller of this frame
* - see Parrot_init_ret_nci(). We therefore invoke the
* return continuation here, which gets rid of this frame
* and returns the real return address
*/
if (cont && cont != NEED_CONTINUATION &&
(PObj_get_FLAGS(cont) & SUB_FLAG_TAILCALL)) {
cont = CONTEXT(interp->ctx)->current_cont;
next = VTABLE_invoke(INTERP, cont, next);
}
return next;
}
/*
=item C<INTVAL get_integer()>
Returns the function pointer as an integer.
=cut
*/
INTVAL get_integer() {
return ((INTVAL)PMC_data(SELF));
}
/*
=item C<INTVAL get_bool()>
Returns the boolean value of the pointer.
=cut
*/
INTVAL get_bool() {
return (0 != (INTVAL)PMC_data(SELF));
}
}
/*
=back
=head1 SEE ALSO
F<docs/pdds/pdd03_calling_conventions.pod>.
=head1 HISTORY
Initial revision by sean 2002/08/04.
=cut
*/
/*
* Local variables:
* c-file-style: "parrot"
* End:
* vim: expandtab shiftwidth=4:
*/
Jump to Line
Something went wrong with that request. Please try again.