From: Scott Wood Date: Sat, 22 Dec 2007 04:23:51 +0000 (-0600) Subject: xfer to loki X-Git-Url: http://git.buserror.net/cgi-bin/gitweb.cgi?p=polintos%2Fscott%2Fpriv.git;a=commitdiff_plain;h=39d6852ead7a839f9e15e21e517dfd7a795e5cdd xfer to loki --- diff --git a/doc/orb/marshalling b/doc/orb/marshalling index e56e350..286eff4 100644 --- a/doc/orb/marshalling +++ b/doc/orb/marshalling @@ -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 diff --git a/doc/orb/parameter-info-block b/doc/orb/parameter-info-block index a61c648..9ad27ee 100644 --- a/doc/orb/parameter-info-block +++ b/doc/orb/parameter-info-block @@ -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 diff --git a/idlcomp/idlc.h b/idlcomp/idlc.h index 651fae6..e030bbe 100644 --- a/idlcomp/idlc.h +++ b/idlcomp/idlc.h @@ -456,6 +456,14 @@ extern int traversal; class Symbol : public RefCountable { 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 { diff --git a/idlcomp/languages/c++/c++.h b/idlcomp/languages/c++/c++.h index ba7e769..9abbebd 100644 --- a/idlcomp/languages/c++/c++.h +++ b/idlcomp/languages/c++/c++.h @@ -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(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 { diff --git a/idlcomp/languages/c++/main.cc b/idlcomp/languages/c++/main.cc index ab4289c..4368bca 100644 --- a/idlcomp/languages/c++/main.cc +++ b/idlcomp/languages/c++/main.cc @@ -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(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(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(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(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(arg2)); + break; + default: BUG(); } diff --git a/idlcomp/languages/c++/marshall.cc b/idlcomp/languages/c++/marshall.cc index bd1f428..46621fe 100644 --- a/idlcomp/languages/c++/marshall.cc +++ b/idlcomp/languages/c++/marshall.cc @@ -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 &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 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; } } diff --git a/idlcomp/types.cc b/idlcomp/types.cc index c22d0be..623b576 100644 --- a/idlcomp/types.cc +++ b/idlcomp/types.cc @@ -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(d->type->get_concrete_sym()); + assert(type); + + if (dynamic_cast(type)) + goto complex; + + Struct *str = dynamic_cast(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) diff --git a/include/c++/orb.h b/include/c++/orb.h index a2ead4d..716b186 100644 --- a/include/c++/orb.h +++ b/include/c++/orb.h @@ -123,6 +123,14 @@ namespace System { uint32_t reserved[3]; // must be zero }; + struct MarshCtx { + GrowableArray &buf; + GrowableArray &objlist; + GrowableArray &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 &buf, - GrowableArray &objlist, - GrowableArray &newobjlist, - ParamInfoBlock::Segment *segs, - int nsegs); - void (*unmarshall)(Array 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 } + } }; } diff --git a/include/c++/util/array.h b/include/c++/util/array.h index 80ba1c7..cc366d2 100644 --- a/include/c++/util/array.h +++ b/include/c++/util/array.h @@ -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; } };