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
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
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
class Symbol : public RefCountable<Symbol> {
NameSpace *ns;
+ void init()
+ {
+ ns = NULL;
+ external = false;
+ priv = false;
+ lang_priv = NULL;
+ }
+
public:
StringRef name;
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)
if (_name)
name->retain();
- ns = NULL;
- external = false;
- priv = false;
-
- memset(traversed, 0, sizeof(traversed));
+ init();
}
virtual ~Symbol();
SymbolRef supersym;
StrListRef supername;
bool attrs_resolved;
+
+ // 0 = unknown, 1 = yes, 2 = no
+ int plain_data;
void add_elem(Datum *d);
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 {
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.
//// 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.
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);
}
}
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 {
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";
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);
}
if (sym->is_virtual())
output_struct_ctor(sym, true);
}
+
+ output_marshall_pass(sym, trav_full);
upscope();
file << indent << "};\n";
break;
}
+
+ case trav_marshall:
+ output_marshall(sym, static_cast<Datum *>(arg2));
+ break;
default:
BUG();
}
break;
+
+ case trav_marshall:
+ output_marshall(sym, static_cast<Datum *>(arg2));
+ break;
default:
BUG();
break;
}
+ case trav_marshall:
+ output_marshall(sym, static_cast<Datum *>(arg2));
+ break;
+
default:
BUG();
}
output_pass(sym, trav_forward);
break;
+ case trav_marshall:
+ output_marshall(sym, static_cast<Datum *>(arg2));
+ break;
+
default:
BUG();
}
output_pass(sym, trav_forward);
break;
+ case trav_marshall:
+ output_marshall(sym, static_cast<Datum *>(arg2));
+ break;
+
default:
BUG();
}
<< 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;
}
}
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)
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
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
return false;
#endif
}
+
}
};
}
bufsize = count;
}
+ // FIXME: use realloc
void grow(size_t newsize)
{
if (newsize <= bufsize)
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();
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;
}
};