]> git.buserror.net Git - polintos/scott/priv.git/commitdiff
xfer to loki
authorScott Wood <scott@thor.buserror.net>
Sat, 22 Dec 2007 04:23:51 +0000 (22:23 -0600)
committerScott Wood <scott@thor.buserror.net>
Sat, 22 Dec 2007 04:23:51 +0000 (22:23 -0600)
doc/orb/marshalling
doc/orb/parameter-info-block
idlcomp/idlc.h
idlcomp/languages/c++/c++.h
idlcomp/languages/c++/main.cc
idlcomp/languages/c++/marshall.cc
idlcomp/types.cc
include/c++/orb.h
include/c++/util/array.h

index e56e350a0d3eebc3c991906f4ad856a9112fc42c..286eff4115b71229c264405d93f84e60165aa156 100644 (file)
@@ -24,7 +24,7 @@ which contain object ids and/or references to other data chunks are
 stored at arbitrary locations in segment 0, and are referenced as an
 offset into the segment.
 
-Data chunks which do not contain object id or references to other
+Data chunks which do not contain object ids or references to other
 data chunks (i.e. they are pure data, and do not need to be altered
 for marshalling) are stored at arbitrary locations in arbitrary
 segments.  References to these pure data chunks are encoded as a
index a61c6485114274e93fb7ac2f52970d31118573ef..9ad27eee0280c19c410ae193808fb372c6655d28 100644 (file)
@@ -26,7 +26,7 @@ Parameter Info Block (PIB)
    objlist_ptr     pointer Pointer to the object list
    newobj_ptr      pointer Pointer to the new object list.
    objlist_len     32-bit  Length of the object list, in IDs
-   newobj_len      32-bit  Length of the new object list.
+   newobj_len      32-bit  Length of the new object list, in hashes.
 
       The object list is a special segment that contains object IDs
       rather than arbitrary data.  Each object ID will be translated
@@ -36,9 +36,10 @@ Parameter Info Block (PIB)
       is the object to receive the message.
 
       Objects which live in this address space have the high bit
-      clear; remote objects have the high bit set.  When sending
-      an object reference that has not been exposed to the kernel
-      before, its interface hash should exist in the newobj list.
+      clear; remote objects have the high bit set.  When sending an
+      object reference that has not been exposed to the kernel
+      before, its interface hash (SHA-1 of interface GUIDs) should
+      exist in the newobj list.
 
    num_segments    32-bit  Number of data segments
 
index 651fae653592a0b42ae6b48f9538f7eeed99fca6..e030bbe52ba5dc355b0068c2f9bb5293c249c5e4 100644 (file)
@@ -456,6 +456,14 @@ extern int traversal;
 class Symbol : public RefCountable<Symbol> {
        NameSpace *ns;
        
+       void init()
+       {
+               ns = NULL;
+               external = false;
+               priv = false;
+               lang_priv = NULL;
+       }
+       
 public:
        StringRef name;
 
@@ -470,19 +478,12 @@ public:
        
        bool priv;
        
-       // This is set to ::traversal when this symbol is visited along a chain.
-       // If a target needs more than 8 simultaneous chains, increase the size
-       // of the array.  These traversals are reserved for language binding use.
-       
-       int traversed[8];
+       // Reserved for language binding use.
+       Releasable *lang_priv;
 
        Symbol()
        {
-               ns = NULL;
-               external = false;
-               priv = false;
-               
-               memset(traversed, 0, sizeof(traversed));
+               init();
        }
        
        Symbol(const String *_name) : name(_name)
@@ -490,11 +491,7 @@ public:
                if (_name)
                        name->retain();
 
-               ns = NULL;
-               external = false;
-               priv = false;
-
-               memset(traversed, 0, sizeof(traversed));
+               init();
        }
 
        virtual ~Symbol();
@@ -1292,6 +1289,9 @@ class Struct : public NameSpace, public Type, public Def {
        SymbolRef supersym;
        StrListRef supername;
        bool attrs_resolved;
+
+       // 0 = unknown, 1 = yes, 2 = no
+       int plain_data;
        
        void add_elem(Datum *d);
 
@@ -1465,6 +1465,10 @@ public:
                def.guid[0] = guid[0];
                def.guid[1] = guid[1];
        }
+
+       // A struct is "plain data" if it contains no object references,
+       // no non-inline arrays or structs, and no inline non-plain structs.
+       bool is_plain_data();
 };
 
 class Param : public Symbol, public Def {
index ba7e769277b75ae91fe2ae1a4f56ca79df98d4f7..9abbebd5cc573da4cf96099dcd0a23dc7ee7c65e 100644 (file)
@@ -27,6 +27,47 @@ void cpp_output_type(ostream &file, CompiledBasicType &t, bool is_mutable);
 
 void cpp_output_one_param(ostream &file, Param *p, bool is_server,
                           bool is_copy = false);
+
+enum CPPTraversal {
+       trav_full,         // Full, final output
+       trav_obj_def,      // Object struct definition
+       trav_obj_stub,     // Object pointer stub,
+                      // so it can be used in structs.
+       trav_nsdecl,       // _ns declaration
+       trav_forward,      // Forward declaration of
+                      // structs/interfaces in nsdecl
+
+       num_traversals,
+       
+       // Values beyond this point are not part of the
+       // above sequential pass scheme; they are merely
+       // for dynamic dispatch.
+       trav_marshall,
+       trav_unmarshall,
+};
+
+// Per-symbol language-private data
+struct CPPData : public Releasable {
+       // The traversal indices are also passed as "arg1" to determine
+       // which pass to generate.  Higher numbers are performed first.
+       
+       int traversed[num_traversals];
+
+       CPPData() : Releasable(1)
+       {
+               memset(traversed, 0, sizeof(traversed));
+       }
+};
+
+static inline CPPData &cpp_symdata(Symbol *sym)
+{
+       if (!sym->lang_priv)
+               sym->lang_priv = new CPPData;
+
+       CPPData *ptr = dynamic_cast<CPPData *>(sym->lang_priv);
+       assert(ptr);
+       return *ptr;
+}
        
 // Each IDL namespace is mapped to a C++ header file,
 // represented by a CPPFile.
@@ -57,7 +98,17 @@ class CPPFile : public LangCallback {
        
        //// Marshalling methods
        
-       void output_marshall(Struct *sym, int pass);
+       void output_marshall_pass(Struct *sym, int pass);
+
+       void output_marshall(Struct *sym, Datum *d);
+       void output_marshall(Interface *sym, Datum *d);
+       void output_marshall(Enum *sym, Datum *d);
+       void output_marshall(BitField *sym, Datum *d);
+       void output_marshall(BasicType *sym, Datum *d);
+       void output_marshall(CompiledBasicType &cbt, Datum *d);
+
+       void align_type(Symbol *sym);
+       void grow_buf(Symbol *sym);
 
        // Output the downcast and implicit upcast methods for
        // the given interface/superinterface pair.
@@ -180,28 +231,15 @@ class CPPFile : public LangCallback {
 
        int first_traversal;
 
-       // The traversal indices are also passed as "arg1" to determine
-       // which pass to generate.  Higher numbers are performed first.
-       
-       enum {
-               trav_full = 0,     // Full, final output
-               trav_obj_def = 1,  // Object struct definition
-               trav_obj_stub = 2, // Object pointer stub,
-                             // so it can be used in structs.
-               trav_nsdecl = 3,   // _ns declaration
-               trav_forward = 4,  // Forward declaration of
-                             // structs/interfaces in nsdecl
-       };
-
        bool pass_needed(Symbol *sym, int pass)
        {
-               return first_traversal > sym->traversed[pass];
+               return first_traversal > cpp_symdata(sym).traversed[pass];
        }
 
        void output_pass(Symbol *sym, int pass)
        {
                if (pass_needed(sym, pass)) {
-                       sym->traversed[pass] = traversal;
+                       cpp_symdata(sym).traversed[pass] = traversal;
                        sym->output_lang(this, pass);
                }
        }
@@ -241,6 +279,18 @@ public:
        void output(Alias *sym, int pass = trav_full, void *arg2 = NULL);
        void output(TypeDef *sym, int pass = trav_full, void *arg2 = NULL);
        void output(Datum *sym, int pass = trav_full, void *arg2 = NULL);
+
+       void marshall(Struct *sym);
+       void marshall(Interface *sym);
+       void marshall(BitField *sym);
+       void marshall(Enum *sym);
+       void marshall(BasicType *sym);
+
+       void unmarshall(Struct *sym);
+       void unmarshall(Interface *sym);
+       void unmarshall(BitField *sym);
+       void unmarshall(Enum *sym);
+       void unmarshall(BasicType *sym);
 };
 
 class CPPBinding : public Language {
index ab4289c596e5c3dee5e3af14e35d0c00e6ef9d47..4368bca4d95bbddb9e56ced6a98dad3c490bfbcd 100644 (file)
@@ -52,7 +52,7 @@ dirname(dir)
                throw UserError();
        }
        
-       file <<   "// " << *ns->get_fq_name()->flatten(".")
+       file <<   "// " << *ns->get_fq_name()->flatten()
             << "\n// This is a C++ language binding generated by idlc.\n"
             <<   "// Do not modify this file directly.\n\n";
 
@@ -640,12 +640,12 @@ void CPPFile::output(Struct *sym, int pass, void *arg2)
                                output_nsdecl_begin(sym);
                                output_nsdecl_children(sym);
                                output_guid(sym->def.guid);
-                               output_marshall(sym, trav_nsdecl);
+                               output_marshall_pass(sym, trav_nsdecl);
                                output_nsdecl_end(sym);
                        } else {
                                output_nsdecl_begin(sym);
                                output_nsdecl_children(sym);
-                               output_marshall(sym, trav_nsdecl);
+                               output_marshall_pass(sym, trav_nsdecl);
                                output_nsdecl_end(sym);
                        }
 
@@ -719,6 +719,8 @@ void CPPFile::output(Struct *sym, int pass, void *arg2)
                                if (sym->is_virtual())
                                        output_struct_ctor(sym, true);
                        }
+                       
+                       output_marshall_pass(sym, trav_full);
 
                        upscope();
                        file << indent << "};\n";
@@ -734,6 +736,10 @@ void CPPFile::output(Struct *sym, int pass, void *arg2)
 
                        break;
                }
+
+               case trav_marshall:
+                       output_marshall(sym, static_cast<Datum *>(arg2));
+                       break;
                
                default:
                        BUG();
@@ -842,6 +848,10 @@ void CPPFile::output(Interface *sym, int pass, void *arg2)
                        }
        
                        break;
+
+               case trav_marshall:
+                       output_marshall(sym, static_cast<Datum *>(arg2));
+                       break;
                
                default:
                        BUG();
@@ -992,6 +1002,10 @@ void CPPFile::output(BitField *sym, int pass, void *arg2)
                        break;
                }
 
+               case trav_marshall:
+                       output_marshall(sym, static_cast<Datum *>(arg2));
+                       break;
+
                default:
                        BUG();
        }
@@ -1062,6 +1076,10 @@ void CPPFile::output(Enum *sym, int pass, void *arg2)
                        output_pass(sym, trav_forward);
                        break;
 
+               case trav_marshall:
+                       output_marshall(sym, static_cast<Datum *>(arg2));
+                       break;
+
                default:
                        BUG();
        }
@@ -1099,6 +1117,10 @@ void CPPFile::output(BasicType *sym, int pass, void *arg2)
                        output_pass(sym, trav_forward);
                        break;
 
+               case trav_marshall:
+                       output_marshall(sym, static_cast<Datum *>(arg2));
+                       break;
+
                default:
                        BUG();
        }
index bd1f4286f0f6a6ceb84278f60bf45f42449e7e35..46621fed92db8b5e371042d83961a3cdb43f5821 100644 (file)
@@ -29,28 +29,116 @@ void CPPFile::output_ifaceinfo(Interface *iface)
             << indent << "::System::RunTime::IFaceInfo _info = {\n"
             << indent << "\t&_guid,\n"
             << indent << "};\n";
+}
+
+void CPPFile::output_marshall(CompiledBasicType &cbt, Datum *d)
+{
+       printf("marshall cbt\n");
+}
+
+void CPPFile::align_type(Symbol *sym)
+{
+       file << indent << "_ctx.buf.align_to(__alignof__(";
+       cpp_output_name(file, sym);
+       file << "));\n";
+}
+
+void CPPFile::grow_buf(Symbol *sym)
+{
+       file << indent << "_ptr = _ctx.buf.grow_by(sizeof(";
+       cpp_output_name(file, sym);
+       file << "));\n";
+}
+
+void CPPFile::output_marshall(Struct *sym, Datum *d)
+{
+       bool is_inline = !d || d->is_inline();
+
+       if (d && !d->is_inline())       {
+               extra_newline();
+               file << indent << "if (" << **d->name << ")\n"
+                    << indent << '\t' << **d->name << "->_marshall(_ctx);\n";
+
+               return;
+       }
+
+       if (!d) {
+               extra_newline();
+               align_type(sym);
+               grow_buf(sym);
+               
+               file << indent << "memcpy(_ptr, this, sizeof(*this));\n";
+       }
+       
+       if (sym->is_plain_data()) {
+               printf("plain data\n");
+               return;
+       }
        
-       do_extra_newline = true;
+       for (Struct::entries_iterator i = sym->entries_begin();
+            i != sym->entries_end(); ++i)
+       {
+               extra_newline();
+               Datum *d = *i;
+               
+               if (d->type)
+                       d->type->output_lang(this, trav_marshall, d);
+               else
+                       output_marshall(d->def.basictype, d);
+       }
+}
+
+void CPPFile::output_marshall(Interface *sym, Datum *d)
+{
+       printf("marshall iface\n");
+}
+
+void CPPFile::output_marshall(Enum *sym, Datum *d)
+{
+       printf("marshall enum\n");
+}
+
+void CPPFile::output_marshall(BitField *sym, Datum *d)
+{
+       printf("marshall bitfield\n");
 }
 
-void CPPFile::output_marshall(Struct *sym, int pass)
+void CPPFile::output_marshall(BasicType *sym, Datum *d)
+{
+       printf("marshall basictype\n");
+}
+
+void CPPFile::output_marshall_pass(Struct *sym, int pass)
 {
        switch (pass) {
                case trav_nsdecl:
                        extra_newline();
                        
-                       file << indent << "int _marshall(::System::RunTime::GrowableArray<uint8_t, ::System::RunTime::ORBMM> &buf,\n"
-                            << indent << "              ::System::RunTime::GrowableArray< ::System::RunTime::ID, ::System::RunTime::ORBMM> &objlist,\n"
-                            << indent << "              ::System::RunTime::GrowableArray< ::System::RunTime::NewObject, ::System::RunTime::ORBMM> &newobjlist,\n"
-                            << indent << "              ::System::RunTime::ParamInfoBlock::Segment *segs,\n"
-                            << indent << "              int nsegs);\n";
+                       file << indent << "int _marshall(::System::RunTime::MarshCtx &_ctx);\n";
+                       file << indent << "void _unmarshall(::System::RunTime::MarshCtx &_ctx);\n";
+                       break;
+
+               case trav_full:
+                       extra_newline();
+
+                       file << indent << "int _marshall(::System::RunTime::MarshCtx &_ctx)\n"
+                            << indent << "{\n"
+                            << indent << "\tvoid *_ptr;\n";
+
+                       indent.indent_level++;
+                       output_marshall(sym, NULL);
+                       indent.indent_level--;
+
+                       file << indent << "\treturn 0;\n"
+                            << indent << "}\n\n";
 
                        file << indent << "void _unmarshall(::System::RunTime::Array<uint8_t, ::System::RunTime::ORBMM> buf,\n"
                             << indent << "                 ::System::RunTime::Array< ::System::_i_Object *, ::System::RunTime::ORBMM> objlist,\n"
                             << indent << "                 ::System::RunTime::ParamInfoBlock::Segment *segs,\n"
-                            << indent << "                 int nsegs);\n";
+                            << indent << "                 int nsegs)\n"
+                            << indent << "{\n"
+                            << indent << "}\n";
 
-                       do_extra_newline = true;
                        break;
        }
 }
index c22d0bef92240b988a2b3cc6e5a4e1fae461bc8d..623b57607f0937bc96fe3f1842052b3abcee5a92 100644 (file)
@@ -348,6 +348,45 @@ void Struct::add_elem(Datum *d)
        def.num_entries++;
 }
 
+bool Struct::is_plain_data()
+{
+       if (!plain_data) {
+               plain_data = 1;
+               for (Struct::entries_iterator i = entries_begin(); i != entries_end(); ++i)
+               {
+                       Datum *d = *i;
+                       if (d->is_array() && !d->def.flags.field.Inline)
+                               goto complex;
+
+                       if (!d->type)
+                               continue;
+
+                       Type *type = dynamic_cast<Type *>(d->type->get_concrete_sym());
+                       assert(type);
+
+                       if (dynamic_cast<Interface *>(type))
+                               goto complex;
+
+                       Struct *str = dynamic_cast<Struct *>(type);
+                       if (str) {
+                               if (!d->def.flags.field.Inline)
+                                       goto complex;
+
+                               // FIXME: check for inline struct loops
+                               if (str->is_plain_data())
+                                       goto complex;
+                       }
+               }
+       }
+       
+       assert(plain_data == 1 || plain_data == 2);
+       return plain_data == 1;
+
+complex:
+       plain_data = 2;
+       return false;
+}
+
 Param *Param::declare(const String *name, NameSpace *parent,
                           StrList *TYPE, CompiledParam::Flags flags,
                           Array *array)
index a2ead4d67fde25486c28f3412fcc0030265c00a1..716b18617837c17e70b3fb4dfa0b2b91c689a80e 100644 (file)
@@ -123,6 +123,14 @@ namespace System {
                        uint32_t reserved[3]; // must be zero
                };
 
+               struct MarshCtx {
+                       GrowableArray<uint8_t, ORBMM> &buf;
+                       GrowableArray<ID, ORBMM> &objlist;
+                       GrowableArray<NewObject, ORBMM> &newobjlist;
+                       ParamInfoBlock::Segment *segs;
+                       int nsegs;
+               };
+
                struct VStructInfo {
                        // List of GUIDs of the struct and its superstructs,
                        // starting with System.VStruct and ending with
@@ -134,17 +142,10 @@ namespace System {
                        
                        const int chainlen;
 
-                       int (*marshall)(GrowableArray<uint8_t, ORBMM> &buf,
-                                       GrowableArray<ID, ORBMM> &objlist,
-                                       GrowableArray<NewObject, ORBMM> &newobjlist,
-                                       ParamInfoBlock::Segment *segs,
-                                       int nsegs);
-                       void (*unmarshall)(Array<uint8_t, ORBMM> buf,
-                                          Array< ::System::_i_Object *, ORBMM> objlist,
-                                          ParamInfoBlock::Segment *segs,
-                                          int nsegs);
+                       int (*marshall)(MarshCtx &ctx);
+                       void (*unmarshall)(MarshCtx &ctx);
                };
-               
+
                namespace Priv {
                        // Return the caller's PC.  It'd be nice if GCC had a builtin for
                        // the current PC, so that a simple relocation could be used rather
@@ -161,6 +162,7 @@ namespace System {
                                return false;
 #endif
                        }
+
                }
        };
 }
index 80ba1c76965b47779ec6003b7f730cb0b6e84396..cc366d2bb9569a0c1dc09efce55e5de81248b52a 100644 (file)
@@ -146,6 +146,7 @@ namespace Util {
                                bufsize = count;
                        }
                        
+                       // FIXME: use realloc
                        void grow(size_t newsize)
                        {
                                if (newsize <= bufsize)
@@ -155,6 +156,7 @@ namespace Util {
                                T *newptr = new(Alloc()) T[newsize];
        
                                memcpy(newptr, ptr, count * sizeof(T));
+                               memset(newptr + count, 0, (newsize - count) * sizeof(T));
        
                                ptr = newptr;
                                ll_smp_membar_store_after_store();
@@ -164,19 +166,41 @@ namespace Util {
                                Alloc::release(oldptr);
                        }
                        
-                       // Caller must sync against all writers.
-                       void append(T *newptr, size_t len, size_t max = ULONG_MAX)
+                       T *grow_by(size_t len, size_t max = ULONG_MAX)
                        {
+                               size_t oldcount = count;
+                       
                                if (count + len < count)
                                        throw ArrayException();
-                               
+
                                if (count + len > max)
                                        throw ArrayException();
-                               
+
                                if (count + len > bufsize)
                                        grow(ll_get_order_round_up(count + len));
-                               
-                               memcpy(ptr + count, newptr, len * sizeof(T));
+
+                               return ptr + oldcount;
+                       }
+
+                       // align must be power-of-two
+                       void align_to(size_t align, size_t max = ULONG_MAX)
+                       {
+                               size_t newcount = (count + align - 1) & ~(align - 1);
+                       
+                               if (newcount < count)
+                                       throw ArrayException();
+
+                               if (newcount > max)
+                                       throw ArrayException();
+
+                               if (newcount > bufsize)
+                                       grow(ll_get_order_round_up(newcount));
+                       }
+                       
+                       // Caller must sync against all writers.
+                       void append(T *newptr, size_t len, size_t max = ULONG_MAX)
+                       {
+                               memcpy(ptr + grow_by(len, max), newptr, len * sizeof(T));
                                count += len;
                        }
                };