[svn:parrot] r47505 - in branches/dynop_mapping: include/parrot src

plobsing at svn.parrot.org plobsing at svn.parrot.org
Wed Jun 9 08:35:08 UTC 2010


Author: plobsing
Date: Wed Jun  9 08:35:08 2010
New Revision: 47505
URL: https://trac.parrot.org/parrot/changeset/47505

Log:
implement bytecode packing/unpacking code to support per-segment mappings

Modified:
   branches/dynop_mapping/include/parrot/packfile.h
   branches/dynop_mapping/src/packfile.c

Modified: branches/dynop_mapping/include/parrot/packfile.h
==============================================================================
--- branches/dynop_mapping/include/parrot/packfile.h	Wed Jun  9 08:22:20 2010	(r47504)
+++ branches/dynop_mapping/include/parrot/packfile.h	Wed Jun  9 08:35:08 2010	(r47505)
@@ -250,16 +250,29 @@
     opcode_t                   const_count;
     PackFile_Constant        **constants;
     PackFile_ByteCode         *code;  /* where this segment belongs to */
-
     PMC                       *string_hash; /* Hash for lookup strings and numbers */
 } PackFile_ConstTable;
 
+typedef struct PackFile_ByteCode_OpMappingEntry {
+    op_lib_t *lib;     /* library for this entry */
+    opcode_t  n_ops;   /* number of ops used */
+    opcode_t *lib_ops; /* indices of ops within the library */
+} PackFile_ByteCode_OpMappingEntry;
+
+typedef struct PackFile_ByteCode_OpMapping {
+    opcode_t                          n_libs; /* number of library entries */
+    PackFile_ByteCode_OpMappingEntry *libs;   /* opcode libraries used by this segment */
+} PackFile_ByteCode_OpMapping;
+
 struct PackFile_ByteCode {
-    PackFile_Segment       base;
-    struct PackFile_Debug *debugs;
-    PackFile_ConstTable   *const_table;
-    PackFile_FixupTable   *fixups;
+    PackFile_Segment             base;
+    struct PackFile_Debug       *debugs;
+    PackFile_ConstTable         *const_table;
+    PackFile_FixupTable         *fixups;
     struct PackFile_Annotations *annotations;
+    PackFile_ByteCode_OpMapping  op_mapping;    /* opcode mapping information */
+    size_t                       op_count;      /* number of ops in the func table */
+    op_func_t                   *op_func_table; /* opcode dispatch table */
 };
 
 typedef struct PackFile_DebugFilenameMapping {

Modified: branches/dynop_mapping/src/packfile.c
==============================================================================
--- branches/dynop_mapping/src/packfile.c	Wed Jun  9 08:22:20 2010	(r47504)
+++ branches/dynop_mapping/src/packfile.c	Wed Jun  9 08:35:08 2010	(r47505)
@@ -25,15 +25,17 @@
 */
 
 #include "parrot/parrot.h"
+#include "parrot/packfile.h"
 #include "parrot/embed.h"
 #include "parrot/extend.h"
-#include "parrot/packfile.h"
+#include "parrot/dynext.h"
 #include "parrot/runcore_api.h"
 #include "../compilers/imcc/imc.h"
 #include "packfile.str"
 #include "pmc/pmc_sub.h"
 #include "pmc/pmc_key.h"
 #include "pmc/pmc_callcontext.h"
+#include "pmc/pmc_parrotlibrary.h"
 
 /* HEADERIZER HFILE: include/parrot/packfile.h */
 
@@ -55,6 +57,31 @@
 
 PARROT_WARN_UNUSED_RESULT
 PARROT_CANNOT_RETURN_NULL
+static opcode_t * byte_code_pack(PARROT_INTERP,
+    ARGMOD(PackFile_Segment *self),
+    ARGOUT(opcode_t *cursor))
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(2)
+        __attribute__nonnull__(3)
+        FUNC_MODIFIES(*self)
+        FUNC_MODIFIES(*cursor);
+
+static size_t byte_code_packed_size(SHIM_INTERP,
+    ARGIN(PackFile_Segment *self))
+        __attribute__nonnull__(2);
+
+PARROT_WARN_UNUSED_RESULT
+PARROT_CANNOT_RETURN_NULL
+static opcode_t * byte_code_unpack(PARROT_INTERP,
+    ARGMOD(PackFile_Segment *self),
+    ARGIN(const opcode_t *cursor))
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(2)
+        __attribute__nonnull__(3)
+        FUNC_MODIFIES(*self);
+
+PARROT_WARN_UNUSED_RESULT
+PARROT_CANNOT_RETURN_NULL
 static PackFile_Constant * clone_constant(PARROT_INTERP,
     ARGIN(PackFile_Constant *old_const))
         __attribute__nonnull__(1)
@@ -352,6 +379,16 @@
     , PARROT_ASSERT_ARG(self))
 #define ASSERT_ARGS_byte_code_new __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp))
+#define ASSERT_ARGS_byte_code_pack __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+       PARROT_ASSERT_ARG(interp) \
+    , PARROT_ASSERT_ARG(self) \
+    , PARROT_ASSERT_ARG(cursor))
+#define ASSERT_ARGS_byte_code_packed_size __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+       PARROT_ASSERT_ARG(self))
+#define ASSERT_ARGS_byte_code_unpack __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+       PARROT_ASSERT_ARG(interp) \
+    , PARROT_ASSERT_ARG(self) \
+    , PARROT_ASSERT_ARG(cursor))
 #define ASSERT_ARGS_clone_constant __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp) \
     , PARROT_ASSERT_ARG(old_const))
@@ -1619,7 +1656,8 @@
 pf_register_standard_funcs(PARROT_INTERP, ARGMOD(PackFile *pf))
 {
     ASSERT_ARGS(pf_register_standard_funcs)
-    PackFile_funcs dirf = {
+
+    static const PackFile_funcs dirf = {
         directory_new,
         directory_destroy,
         directory_packed_size,
@@ -1628,7 +1666,7 @@
         directory_dump
     };
 
-    PackFile_funcs defaultf = {
+    static const PackFile_funcs defaultf = {
         PackFile_Segment_new,
         (PackFile_Segment_destroy_func_t)     NULLfunc,
         (PackFile_Segment_packed_size_func_t) NULLfunc,
@@ -1637,7 +1675,7 @@
         default_dump
     };
 
-    PackFile_funcs fixupf = {
+    static const PackFile_funcs fixupf = {
         fixup_new,
         fixup_destroy,
         fixup_packed_size,
@@ -1646,7 +1684,7 @@
         default_dump
     };
 
-    PackFile_funcs constf = {
+    static const PackFile_funcs constf = {
         const_new,
         const_destroy,
         PackFile_ConstTable_pack_size,
@@ -1655,16 +1693,16 @@
         default_dump
     };
 
-    PackFile_funcs bytef = {
+    static const PackFile_funcs bytef = {
         byte_code_new,
         byte_code_destroy,
-        (PackFile_Segment_packed_size_func_t) NULLfunc,
-        (PackFile_Segment_pack_func_t)        NULLfunc,
-        (PackFile_Segment_unpack_func_t)      NULLfunc,
+        byte_code_packed_size,
+        byte_code_pack,
+        byte_code_unpack,
         default_dump
     };
 
-    const PackFile_funcs debugf = {
+    static const PackFile_funcs debugf = {
         pf_debug_new,
         pf_debug_destroy,
         pf_debug_packed_size,
@@ -1673,7 +1711,7 @@
         pf_debug_dump
     };
 
-    const PackFile_funcs annotationf = {
+    static const PackFile_funcs annotationf = {
         PackFile_Annotations_new,
         PackFile_Annotations_destroy,
         PackFile_Annotations_packed_size,
@@ -2582,9 +2620,16 @@
     ASSERT_ARGS(byte_code_destroy)
     PackFile_ByteCode * const byte_code = (PackFile_ByteCode *)self;
 
-    byte_code->fixups      = NULL;
-    byte_code->const_table = NULL;
-    byte_code->debugs      = NULL;
+    if (byte_code->op_func_table)
+        mem_gc_free(interp, byte_code->op_func_table);
+    if (byte_code->op_mapping.libs)
+        mem_gc_free(interp, byte_code->op_mapping.libs);
+
+    byte_code->fixups          = NULL;
+    byte_code->const_table     = NULL;
+    byte_code->debugs          = NULL;
+    byte_code->op_mapping.libs = NULL;
+    byte_code->op_func_table   = NULL;
 }
 
 
@@ -2610,6 +2655,139 @@
     return (PackFile_Segment *) byte_code;
 }
 
+static size_t
+byte_code_packed_size(SHIM_INTERP, ARGIN(PackFile_Segment *self))
+{
+    ASSERT_ARGS(byte_code_packed_size)
+    PackFile_ByteCode * const byte_code = (PackFile_ByteCode *)self;
+    size_t size;
+    int i;
+
+    size = 1; /* n_libs */
+
+    for (i = 0; i < byte_code->op_mapping.n_libs; i++) {
+        PackFile_ByteCode_OpMappingEntry * const entry = &byte_code->op_mapping.libs[i];
+
+        /* dynoplib data */
+        size += PF_size_cstring(entry->lib->name);
+        size += 3; /* major + minor + patch */
+
+        /* op entries */
+        size += 1;            /* n_ops */
+        size += entry->n_ops; /* lib_ops */
+    }
+
+    return size;
+}
+
+PARROT_WARN_UNUSED_RESULT
+PARROT_CANNOT_RETURN_NULL
+static opcode_t *
+byte_code_pack(PARROT_INTERP, ARGMOD(PackFile_Segment *self), ARGOUT(opcode_t *cursor))
+{
+    ASSERT_ARGS(byte_code_pack)
+    PackFile_ByteCode * const byte_code = (PackFile_ByteCode *)self;
+    int i, j;
+
+    *cursor++ = byte_code->op_mapping.n_libs;
+
+    for (i = 0; i < byte_code->op_mapping.n_libs; i++) {
+        PackFile_ByteCode_OpMappingEntry * const entry = &byte_code->op_mapping.libs[i];
+
+        /* dynoplib data */
+        cursor    = PF_store_cstring(cursor, entry->lib->name);
+        *cursor++ = entry->lib->major_version;
+        *cursor++ = entry->lib->minor_version;
+        *cursor++ = entry->lib->patch_version;
+
+        /* op entries */
+        *cursor++ = entry->n_ops;
+        for (j = 0; j < entry->n_ops; j++)
+            *cursor++ = entry->lib_ops[j];
+    }
+
+    return cursor;
+}
+
+PARROT_WARN_UNUSED_RESULT
+PARROT_CANNOT_RETURN_NULL
+static opcode_t *
+byte_code_unpack(PARROT_INTERP, ARGMOD(PackFile_Segment *self), ARGIN(const opcode_t *cursor))
+{
+    ASSERT_ARGS(byte_code_unpack)
+    PackFile_ByteCode * const byte_code = (PackFile_ByteCode *)self;
+    int i;
+
+    byte_code->op_count          = 0;
+    byte_code->op_func_table     = NULL;
+
+    byte_code->op_mapping.n_libs = PF_fetch_opcode(self->pf, &cursor);
+    byte_code->op_mapping.libs   = mem_gc_allocate_n_zeroed_typed(interp,
+                                    byte_code->op_mapping.n_libs,
+                                    PackFile_ByteCode_OpMappingEntry);
+
+    for (i = 0; i < byte_code->op_mapping.n_libs; i++) {
+        PackFile_ByteCode_OpMappingEntry * const entry = &byte_code->op_mapping.libs[i];
+
+        /* dynoplib data */
+        {
+            char * const    lib_name = PF_fetch_cstring(interp, self->pf, &cursor);
+            const opcode_t  major    = PF_fetch_opcode(self->pf, &cursor);
+            const opcode_t  minor    = PF_fetch_opcode(self->pf, &cursor);
+            const opcode_t  patch    = PF_fetch_opcode(self->pf, &cursor);
+            const PMC      *lib_pmc  = Parrot_load_lib(interp,
+                                        Parrot_str_new(interp, lib_name, 0),
+                                        NULL);
+
+            mem_gc_free(interp, lib_name);
+
+            {
+                /* XXX
+                 * broken encapsulation => should make this data easier to access somehow
+                 */
+                void *oplib_init;
+                op_lib_t *(*oplib_init_f)(PARROT_INTERP, long init);
+                GETATTR_ParrotLibrary_oplib_init(interp, lib_pmc, oplib_init);
+                oplib_init_f = D2FPTR(oplib_init);
+                entry->lib = oplib_init_f(interp, 1);
+            }
+
+            if (entry->lib->major_version != major
+            ||  entry->lib->minor_version != minor
+            ||  entry->lib->patch_version != patch)
+                Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_LIBRARY_ERROR,
+                    "Incompatible versions of `%s' library. Found %d.%d.%d but loaded %d.%d.%d",
+                    entry->lib->name, major, minor, patch, entry->lib->major_version,
+                    entry->lib->minor_version, entry->lib->patch_version);
+        }
+
+        /* op entries */
+        {
+            int       j;
+            const int old_op_count = byte_code->op_count;
+            byte_code->op_count += entry->n_ops = PF_fetch_opcode(self->pf, &cursor);
+
+            if (!byte_code->op_func_table)
+                byte_code->op_func_table = mem_gc_allocate_n_typed(interp,
+                                            byte_code->op_count, op_func_t);
+            else
+                mem_gc_realloc_n_typed(interp, byte_code->op_func_table,
+                    byte_code->op_count, op_func_t);
+
+            for (j = 0; j < entry->n_ops; j++) {
+                int op = PF_fetch_opcode(self->pf, &cursor);
+                if (0 < op || op < entry->lib->op_count)
+                    Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_MALFORMED_PACKFILE,
+                        "opcode index out of bounds on library `%s'. Found %d, expection 0 to %d.",
+                        entry->lib->name, op, entry->lib->op_count);
+                entry->lib_ops[j]                          = op;
+                byte_code->op_func_table[old_op_count + j] = entry->lib->op_func_table[j];
+            }
+        }
+    }
+
+    return cursor;
+}
 
 /*
 


More information about the parrot-commits mailing list