# New Ticket Created by  Jürgen Bömmels 
# Please include the string:  [perl #23034]
# in the subject line of all future correspondence about this issue. 
# <URL: http://rt.perl.org/rt2/Ticket/Display.html?id=23034 >


Hi,

During searching for memory leaks and hunting bugs only visible on
MacOS, I started a little fun project:
Implementation of methods for the ParrotIO-PMCs.

Actually this is the first pmc implementing the find_method
vtable-call.

The implementation is quite simple: find_method returns an nci-object
which calls the corresponding PIO-function. So far so simple.

But for this to work, i needed to extend the prototype-system of the
native call interface. Currently there is no way to pass a PMC down to
the native function, so I implemented a new type-letter 'P' for a PMC*
valued function (only jit/i386 and call_list.txt).

QUESTION: The calling convention for methods states that P2 should be
the object the sub was called on. The current build_call_frames pushes
the object starting at P5. How can the NCI-Interface be extended to
pass objects in P2 down to the c-functions?

The NCI-Objects are created at class_init time and stored in a
PerlHash. Therefor PerlHash and PerlUndef must get initialised in the
class_init of ParrotIO.

QUESTION: The class initialisation code seems strange to me. Will the
class initialisation be called once for each interpreter (there are
interpreter variables in there) or once for each program start (the
classes are entered in a static array Parrot_base_vtables)?

All tests passed on Linux/i386 with and without JIT.

bye
boe



-- attachment  1 ------------------------------------------------------
url: http://rt.perl.org/rt2/attach/61285/45241/900fb2/io14.diff

? make_test_imcc
Index: build_nativecall.pl
===================================================================
RCS file: /cvs/public/parrot/build_nativecall.pl,v
retrieving revision 1.14
diff -u -r1.14 build_nativecall.pl
--- build_nativecall.pl	14 Jun 2003 17:48:31 -0000	1.14
+++ build_nativecall.pl	18 Jul 2003 06:46:48 -0000
@@ -201,6 +201,9 @@
     /I/ && do {
 	       return "interpreter";
               };
+    /P/ && do {my $regnum = $reg_ref->{p}++;
+               return "PMC_REG($regnum)";
+              };
 
 }
 
Index: call_list.txt
===================================================================
RCS file: /cvs/public/parrot/call_list.txt,v
retrieving revision 1.8
diff -u -r1.8 call_list.txt
--- call_list.txt	18 Jan 2003 09:14:30 -0000	1.8
+++ call_list.txt	18 Jul 2003 06:46:48 -0000
@@ -13,6 +13,7 @@
 # t - character string
 # PMC reg stuff
 # p - data pointer from PMC (on store into a new UnManagedStruct PMC)
+# P - pointer to a PMC-register
 # special stuff
 # I - Parrot_Interp param
 #
@@ -39,3 +40,10 @@
 i	pppp
 i	ppi
 p	It
+# These are needed for parrotio.pmc
+i	IP
+v	IP
+i	IPi
+i	IPii
+i	IPiii
+i	IPt
Index: interpreter.c
===================================================================
RCS file: /cvs/public/parrot/interpreter.c,v
retrieving revision 1.171
diff -u -r1.171 interpreter.c
--- interpreter.c	16 Jul 2003 12:53:01 -0000	1.171
+++ interpreter.c	18 Jul 2003 06:46:49 -0000
@@ -503,6 +503,9 @@
      * mem_setup_allocator() is called. */
     interpreter->flags = flags;
 
+    /* Set up the memory allocation system */
+    mem_setup_allocator(interpreter);
+
     /* PANIC will fail until this is done */
     SET_NULL(interpreter->piodata);
     PIO_init(interpreter);
@@ -517,9 +520,6 @@
                 "with DISABLE_GC_DEBUG.\n");
 #endif
     }
-
-    /* Set up the memory allocation system */
-    mem_setup_allocator(interpreter);
 
     /* initialize classes */
     Parrot_init(interpreter, 0);
Index: classes/parrotio.pmc
===================================================================
RCS file: /cvs/public/parrot/classes/parrotio.pmc,v
retrieving revision 1.4
diff -u -r1.4 parrotio.pmc
--- classes/parrotio.pmc	9 Jul 2003 08:33:11 -0000	1.4
+++ classes/parrotio.pmc	18 Jul 2003 06:46:50 -0000
@@ -13,12 +13,62 @@
 
 #include "parrot/parrot.h"
 
+static void
+enter_nci_method(struct Parrot_Interp *interpreter, PMC *method_table,
+		 void *func, const char *name, const char *proto)
+{
+    PMC *method;
+
+    method = pmc_new(interpreter, enum_class_NCI);
+    VTABLE_set_string_keyed(interpreter, method, func, 
+			    string_make(interpreter, proto, strlen(proto),
+					NULL, 0, NULL));
+    VTABLE_set_pmc_keyed(interpreter, method_table,
+			 key_new_string(interpreter,
+					string_make(interpreter, name,
+						    strlen(name), NULL,
+						    0, NULL)),
+			 method);
+}
+
 pmclass ParrotIO {
 
     STRING* name () {
 	return whoami;
     }
 
+    void class_init () {
+        PMC *method_table;;
+
+        /* These classes are needed now so make sure they are inited */
+        Parrot_NCI_class_init(interp, enum_class_NCI);
+        Parrot_PerlHash_class_init(interp, enum_class_PerlHash);
+        Parrot_PerlUndef_class_init(interp, enum_class_PerlUndef);
+
+        method_table = pmc_new(INTERP, enum_class_PerlHash);
+
+        enter_nci_method(INTERP, method_table,
+                         F2DPTR(PIO_close), "close", "iIP");
+        enter_nci_method(INTERP, method_table,
+                         F2DPTR(PIO_flush), "flush", "vIP");
+        enter_nci_method(INTERP, method_table,
+                         F2DPTR(PIO_read), "read", "iIPii");
+        enter_nci_method(INTERP, method_table,
+                         F2DPTR(PIO_write), "write", "iIPii");
+        enter_nci_method(INTERP, method_table,
+                         F2DPTR(PIO_setbuf), "setbuf", "iIPi");
+        enter_nci_method(INTERP, method_table,
+                         F2DPTR(PIO_setlinebuf), "setlinebuf", "iIP");
+        enter_nci_method(INTERP, method_table,
+                         F2DPTR(PIO_puts), "puts", "iIPt");
+        enter_nci_method(INTERP, method_table,
+                         F2DPTR(PIO_seek), "seek", "iIPiii");
+        enter_nci_method(INTERP, method_table,
+                         F2DPTR(PIO_eof), "eof", "iIP");
+
+        ((ParrotIOData *)(INTERP->piodata))->method_table = method_table;
+    }
+
     void init () {
 	PObj_active_destroy_SET(SELF);
 	PObj_needs_early_DOD_SET(SELF);
@@ -42,5 +92,12 @@
 
     INTVAL get_bool() {
 	return !PIO_eof(INTERP, SELF);
+    }
+
+    PMC* find_method (STRING* name) {
+        PMC* method_table = ((ParrotIOData *)(INTERP->piodata))->method_table;
+
+	return VTABLE_get_pmc_keyed(INTERP, method_table, 
+				    key_new_string(INTERP, name));
     }
 }
Index: include/parrot/io.h
===================================================================
RCS file: /cvs/public/parrot/include/parrot/io.h,v
retrieving revision 1.34
diff -u -r1.34 io.h
--- include/parrot/io.h	3 Jul 2003 10:03:57 -0000	1.34
+++ include/parrot/io.h	18 Jul 2003 06:46:52 -0000
@@ -166,6 +166,7 @@
 struct _ParrotIOData {
     ParrotIOTable table;
     ParrotIOLayer *default_stack;
+    PMC *method_table;
 };
 
 
Index: jit/i386/jit_emit.h
===================================================================
RCS file: /cvs/public/parrot/jit/i386/jit_emit.h,v
retrieving revision 1.68
diff -u -r1.68 jit_emit.h
--- jit/i386/jit_emit.h	9 Jul 2003 10:31:55 -0000	1.68
+++ jit/i386/jit_emit.h	18 Jul 2003 06:46:54 -0000
@@ -2484,7 +2484,7 @@
     const char *typs[] = {
         "lisc", /* I */
         "t",    /* S */
-        "p",    /* P */
+        "pP",   /* P */
         "fd"   /* N */
     };
     int first_reg = 5;
@@ -2589,6 +2589,11 @@
                 emitm_movl_m_r(pc, emit_EAX, emit_EAX, 0, 1,
                         offsetof(struct PMC_EXT, data));
 #endif
+                emitm_pushl_r(pc, emit_EAX);
+                break;
+            case 'P':   /* push PMC * */
+                jit_emit_mov_rm_i(pc, emit_EAX,
+                        &PMC_REG(count_regs(sig, signature->strstart)));
                 emitm_pushl_r(pc, emit_EAX);
                 break;
             case 'v':
Index: t/pmc/io.t
===================================================================
RCS file: /cvs/public/parrot/t/pmc/io.t,v
retrieving revision 1.5
diff -u -r1.5 io.t
--- t/pmc/io.t	9 Jul 2003 19:27:05 -0000	1.5
+++ t/pmc/io.t	18 Jul 2003 06:46:55 -0000
@@ -1,6 +1,6 @@
 #! perl -w
 
-use Parrot::Test tests => 17;
+use Parrot::Test tests => 18;
 use Test::More;
 
 output_is(<<'CODE', <<'OUTPUT', "open/close");
@@ -256,4 +256,14 @@
 1.000000
 foo
 This is a test
+OUTPUT
+
+output_is(<<'CODE', <<'OUTPUT', 'puts method');
+       set S5, "ok\n"
+       getstdout P5
+       find_method P0, P5, "puts"
+       invoke
+       end
+CODE
+ok
 OUTPUT
-- 
Juergen Boemmels                        [EMAIL PROTECTED]
Fachbereich Physik                      Tel: ++49-(0)631-205-2817
Universitaet Kaiserslautern             Fax: ++49-(0)631-205-3906
PGP Key fingerprint = 9F 56 54 3D 45 C1 32 6F  23 F6 C7 2F 85 93 DD 47

Reply via email to