All -- Based on the recent exchange between Dan and I, I've revised the dynamic oplib loading patch. Now, there is a op_lib_init() function that gets called. It returns a pointer to an op_lib_t, which contains the name of the oplib, the number of ops, and pointers to the op_info and op_func arrays.
These pointers and op count are cached in the interpreter to avoid the extra dereferences that would otherwise be required in the inner loop. Note that Simon's vtable.ops is now converted to a shared dynamic library, too. We'll have to solve the multiple oplibs issue before it can be used unless we're going to create the *true* core.ops by concatenating the current core.ops and the generated vtable.ops. Let me know what you think, -- Gregor
Index: Makefile.in =================================================================== RCS file: /home/perlcvs/parrot/Makefile.in,v retrieving revision 1.35 diff -a -u -r1.35 Makefile.in --- Makefile.in 2001/10/18 11:33:47 1.35 +++ Makefile.in 2001/10/20 20:08:26 @@ -6,13 +6,15 @@ H_FILES = $(INC)/config.h $(INC)/exceptions.h $(INC)/io.h $(INC)/op.h \ $(INC)/register.h $(INC)/string.h $(INC)/events.h $(INC)/interpreter.h \ $(INC)/memory.h $(INC)/parrot.h $(INC)/stacks.h $(INC)/packfile.h \ -$(INC)/global_setup.h $(INC)/vtable.h $(INC)/oplib/core_ops.h \ -$(INC)/runops_cores.h $(INC)/trace.h $(INC)/oplib/vtable_ops.h +$(INC)/global_setup.h $(INC)/vtable.h \ +$(INC)/runops_cores.h $(INC)/trace.h +STRING_OBJS=string$(O) strnative$(O) strutf8$(O) strutf16$(O) strutf32$(O) \ +transcode$(O) + O_FILES = global_setup$(O) interpreter$(O) parrot$(O) register$(O) \ -core_ops$(O) memory$(O) packfile$(O) stacks$(O) string$(O) strnative$(O) \ -strutf8$(O) strutf16$(O) strutf32$(O) transcode$(O) runops_cores$(O) \ -trace$(O) vtable_ops$(O) +memory$(O) packfile$(O) stacks$(O) runops_cores$(O) \ +trace$(O) $(STRING_OBJS) #DO NOT ADD C COMPILER FLAGS HERE #Add them in Configure.pl--look for the @@ -38,9 +40,18 @@ libparrot.so: $(O_FILES) $(CC) -shared $(C_LIBS) -o $@ $(O_FILES) + +libcore_ops.so: core_ops$(O) + $(CC) -shared -o $@ core_ops$(O) + +libvtable_ops.so: vtable_ops$(O) + $(CC) -shared -o $@ vtable_ops$(O) + +libparrot_string.so: $(STRING_OBJS) + $(CC) -shared -o $@ $(STRING_OBJS) -$(TEST_PROG): test_main$(O) $(O_FILES) Parrot/OpLib/core.pm - $(CC) $(CFLAGS) -o $(TEST_PROG) $(O_FILES) test_main$(O) $(C_LIBS) +$(TEST_PROG): test_main$(O) $(O_FILES) Parrot/OpLib/core.pm libcore_ops.so + $(CC) -rdynamic $(CFLAGS) -o $(TEST_PROG) $(O_FILES) test_main$(O) $(C_LIBS) +-ldl $(PDUMP): pdump$(O) packfile$(O) memory$(O) global_setup$(O) string$(O) strnative$(O) strutf8$(O) strutf16$(O) strutf32$(O) transcode$(O) $(CC) $(CFLAGS) -o $(PDUMP) pdump$(O) packfile$(O) memory$(O) global_setup$(O) string$(O) strnative$(O) strutf8$(O) strutf16$(O) strutf32$(O) transcode$(O) $(C_LIBS) @@ -119,6 +130,7 @@ $(RM_F) examples/assembly/mops$(EXE) examples/assembly/mops.c $(RM_F) examples/assembly/mops$(O) examples/assembly/mops.pbc $(RM_F) Parrot/OpLib/core.pm + $(RM_F) libcore_ops.so libvtable_ops.so cd docs; make clean test: $(TEST_PROG) assemble.pl .test_dummy Index: interpreter.c =================================================================== RCS file: /home/perlcvs/parrot/interpreter.c,v retrieving revision 1.32 diff -a -u -r1.32 interpreter.c --- interpreter.c 2001/10/18 01:15:11 1.32 +++ interpreter.c 2001/10/20 20:08:26 @@ -12,10 +12,15 @@ #include "parrot/parrot.h" #include "parrot/interp_guts.h" -#include "parrot/oplib/core_ops.h" +/* #include "parrot/oplib/core_ops.h" */ #include "parrot/runops_cores.h" +#include "parrot/op.h" +#include <dlfcn.h> +#define OP_LIB "core_ops" + + /*=for api interpreter check_fingerprint * TODO: Not really part of the API, but here's the docs. * Check the bytecode's opcode table fingerprint. @@ -100,10 +105,10 @@ int i; if (interpreter->profile == NULL) { - interpreter->profile = (INTVAL *)mem_sys_allocate(core_numops * sizeof(INTVAL)); + interpreter->profile = (INTVAL +*)mem_sys_allocate(interpreter->op_count * sizeof(INTVAL)); } - for (i = 0; i < core_numops; i++) { + for (i = 0; i < interpreter->op_count; i++) { interpreter->profile[i] = 0; } } @@ -117,7 +122,10 @@ */ struct Parrot_Interp * make_interpreter() { - struct Parrot_Interp *interpreter; + struct Parrot_Interp * interpreter; + void * oplib_handle; + op_lib_t * (*op_lib_init)(void); + /* Get an empty interpreter from system memory */ interpreter = mem_sys_allocate((INTVAL)sizeof(struct Parrot_Interp)); /* Set up the memory allocation system */ @@ -179,10 +187,33 @@ /* Need an empty stash */ interpreter->perl_stash = mem_allocate_new_stash(); - /* Load the core op func and info tables */ + /* Load the oplib */ + + oplib_handle = dlopen("libcore_ops.so", RTLD_LAZY); + if (oplib_handle == NULL) { + fprintf(stderr, "parrot: Unable to open 'libcore_ops.so' library: %s.\n", +dlerror()); + exit(1); + } + + op_lib_init = dlsym(oplib_handle, "op_lib_init"); + + if (op_lib_init == NULL) { + fprintf(stderr, "parrot: Unable to locate 'op_lib_init' member: %s.\n", +dlerror()); + dlclose(oplib_handle); + exit(1); + } + + interpreter->op_lib = (*op_lib_init)(); + + if (interpreter->op_lib == NULL) { + fprintf(stderr, "parrot: Failed to initialize op lib!\n"); + dlclose(oplib_handle); + exit(1); + } - interpreter->opcode_funcs = core_opfunc; - interpreter->opcode_info = core_opinfo; + interpreter->op_count = interpreter->op_lib->op_count; + interpreter->op_info = interpreter->op_lib->op_info; + interpreter->op_func = interpreter->op_lib->op_func; /* In case the I/O system needs something */ Init_IO(interpreter); Index: ops2c.pl =================================================================== RCS file: /home/perlcvs/parrot/ops2c.pl,v retrieving revision 1.3 diff -a -u -r1.3 ops2c.pl --- ops2c.pl 2001/10/18 00:21:03 1.3 +++ ops2c.pl 2001/10/20 20:08:26 @@ -73,12 +73,10 @@ print HEADER $preamble; print HEADER <<END_C; #include "parrot/parrot.h" +#include "parrot/oplib.h" -extern INTVAL ${base}_numops; +/* Do we really need this header file anymore? */ -extern op_func_t ${base}_opfunc[$num_entries]; -extern op_info_t ${base}_opinfo[$num_entries]; - END_C print SOURCE $preamble; @@ -91,13 +89,11 @@ print SOURCE <<END_C; -INTVAL ${base}_numops = $num_ops; - /* ** Op Function Table: */ -op_func_t ${base}_opfunc[$num_entries] = { +op_func_t op_func[$num_entries] = { END_C @@ -150,7 +146,7 @@ ** Op Info Table: */ -op_info_t ${base}_opinfo[$num_entries] = { +op_info_t op_info[$num_entries] = { END_C $index = 0; @@ -181,6 +177,23 @@ print SOURCE <<END_C; }; + + +/* +** op lib descriptor +*/ + +op_lib_t op_lib = { + "$base", + $num_ops, + op_info, + op_func +}; + + +op_lib_t * op_lib_init(void) { + return &op_lib; +} END_C Index: test_main.c =================================================================== RCS file: /home/perlcvs/parrot/test_main.c,v retrieving revision 1.17 diff -a -u -r1.17 test_main.c --- test_main.c 2001/10/14 23:47:39 1.17 +++ test_main.c 2001/10/20 20:08:26 @@ -12,8 +12,6 @@ #include "parrot/parrot.h" -#include "parrot/oplib/core_ops.h" - int main(int argc, char **argv) { int i; @@ -167,12 +165,12 @@ printf(" CODE OP FULL NAME CALLS\n"); printf(" ----- ------------ ------------\n"); - for (i = 0; i < core_numops; i++) { + for (i = 0; i < interpreter->op_count; i++) { if(interpreter->profile[i] > 0) { op_count++; call_count += interpreter->profile[i]; - printf(" %5d %-12s %12d\n", i, core_opinfo[i].full_name, + printf(" %5d %-12s %12d\n", i, +interpreter->op_info[i].full_name, interpreter->profile[i]); } Index: trace.c =================================================================== RCS file: /home/perlcvs/parrot/trace.c,v retrieving revision 1.1 diff -a -u -r1.1 trace.c --- trace.c 2001/10/18 01:15:11 1.1 +++ trace.c 2001/10/20 20:08:26 @@ -23,13 +23,13 @@ INTVAL i; fprintf(stderr, "PC=%ld; OP=%ld (%s)", (long)(pc - code_start), *pc, - interpreter->opcode_info[*pc].full_name); + interpreter->op_info[*pc].full_name); - if (interpreter->opcode_info[*pc].arg_count > 1) { + if (interpreter->op_info[*pc].arg_count > 1) { fprintf(stderr, "; ARGS=("); - for(i = 1; i < interpreter->opcode_info[*pc].arg_count; i++) { + for(i = 1; i < interpreter->op_info[*pc].arg_count; i++) { if (i > 1) { fprintf(stderr, ", "); } - switch(interpreter->opcode_info[*pc].types[i]) { + switch(interpreter->op_info[*pc].types[i]) { case PARROT_ARG_IC: fprintf(stderr, "%ld", (long) *(pc + i)); break; Index: include/parrot/interp_guts.h =================================================================== RCS file: /home/perlcvs/parrot/include/parrot/interp_guts.h,v retrieving revision 1.1 diff -a -u -r1.1 interp_guts.h --- include/parrot/interp_guts.h 2001/10/14 00:43:50 1.1 +++ include/parrot/interp_guts.h 2001/10/20 20:08:26 @@ -5,7 +5,7 @@ #ifndef INTERP_GUTS_H #define INTERP_GUTS_H -#define DO_OP(PC,INTERP) PC = ((INTERP->opcode_funcs)[*PC])(PC,INTERP); +#define DO_OP(PC,INTERP) PC = ((INTERP->op_func)[*PC])(PC,INTERP); #endif /* INTERP_GUTS_H */ Index: include/parrot/interpreter.h =================================================================== RCS file: /home/perlcvs/parrot/include/parrot/interpreter.h,v retrieving revision 1.12 diff -a -u -r1.12 interpreter.h --- include/parrot/interpreter.h 2001/10/18 01:15:11 1.12 +++ include/parrot/interpreter.h 2001/10/20 20:08:26 @@ -16,6 +16,7 @@ #include "parrot/parrot.h" #include "parrot/op.h" +#include "parrot/oplib.h" struct Parrot_Interp { struct IReg *int_reg; /* Current top of int reg stack */ @@ -33,8 +34,11 @@ struct Arenas *arena_base; /* Pointer to this */ /* interpreter's arena */ - op_info_t * opcode_info; /* Opcode info table (name, nargs, arg types) */ - opcode_t *(**opcode_funcs)(); /* Opcode function table */ + op_lib_t * op_lib; /* The opcode library */ + INTVAL op_count; /* The number of opcodes */ + op_info_t * op_info; /* Opcode info table (name, nargs, arg +types) */ + opcode_t *(**op_func)(); /* Opcode function table */ + STRING_FUNCS *(**string_funcs)(); /* String function table */ INTVAL flags; /* Various interpreter flags that signal that runops Index: include/parrot/oplib.h =================================================================== RCS file: oplib.h diff -N oplib.h --- /dev/null Sat Oct 20 04:18:21 2001 +++ oplib.h Sat Oct 20 13:08:26 2001 @@ -0,0 +1,42 @@ +/* oplib.h + * Copyright: (When this is determined...it will go here) + * CVS Info + * $Id: $ + * Overview: + * Header file for op libraries. + * Data Structure and Algorithms: + * History: + * Notes: + * References: + */ + +#if !defined(PARROT_OPLIB_H_GUARD) +#define PARROT_OPLIB_H_GUARD + +#include "parrot/config.h" +#include "parrot/op.h" + + +/* +** op_lib_t +*/ + +typedef struct { + char * name; + INTVAL op_count; + op_info_t * op_info; + op_func_t * op_func; +} op_lib_t; + + +#endif + +/* + * Local variables: + * c-indentation-style: bsd + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + * + * vim: expandtab shiftwidth=4: +*/