eax: pointer to exception, or NULL if none
edx: length of exception segment, if any
ebx, esi, edi, ebp, esp: may be clobbered
-
-Object registration:
- eax: number of objects to register with initial refcount 1
- edx: pointer to list of NewObject structs
-
- Call the 32-bit address stored at 0x7fff0008.
-
- Upon return:
- eax: pointer to exception, or NULL if none
- edx: length of exception segment, if any
-
-GUID SHA-1 hash retrieval:
- eax: object id
- edx: 20-byte buffer
-
- Call the 32-bit address stored at 0x7fff000c.
-
- Upon return:
- eax: pointer to exception, or NULL if none
- edx: length of exception segment, if any
This is like buffer_size, but for Copy segments.
objlist_ptr pointer Pointer to the object list
- newobj_ptr pointer Pointer to the new 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.
The object list is a special segment that contains object IDs
rather than arbitrary data. Each object ID will be translated
regardless of the pointer size. The first object in the list
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.
-
-
+ 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.
num_segments 32-bit Number of data segments
read-only), which can be overridden with custom getters and setters
in the class.
-Methods can be specified as read-only; a read-only version of the
-interface is then generated, and a secure read-only reference to an
-object can be generated that can only access read-only methods. This
-would save effort declaring a separate interface and a separate
-class.
-
Implement marshalling/unmarshalling stubs.
Implement async methods.
can only be used when invoked as a sync in-process method; the method
implementation can check to see how it was invoked, and use the out
parameters to avoid having to make a completion callback.
+
+Use linker section garbage collection to discard GUIDs, vtables, etc. for
+interfaces/vstructs that aren't referenced.
// The implementation is delayed to avoid circular dependency problems.
void output_casts(Interface *sym);
+
+ //// Marshalling methods
+
+ void output_marshall(Struct *sym, int pass);
// Output the downcast and implicit upcast methods for
// the given interface/superinterface pair.
void CPPFile::output_downcast_proto(Interface *iface, Interface *super)
{
- file << '\n' << indent << "static inline " << **iface->name << " downcast(";
+ file << '\n' << indent << "static __attribute__((weak)) inline "
+ << **iface->name << " downcast(";
cpp_output_type(file, super, false, false);
file << "oldptr);\n";
}
const unsigned char *guid = reinterpret_cast<const unsigned char *>(guid64);
char guidhex[7];
- file << indent << "static const __attribute__((unused))\n"
+ file << indent << "__attribute__((weak))\n"
<< indent << "::System::RunTime::GUID _guid = {\n"
<< indent << "\t{ ";
{
all_ns_in(sym, true, "VINFO_");
- file << indent << "static const __attribute__((unused)) "
- "unsigned long *const _guids[] = {\n";
+ file << indent << "__attribute__((weak)) "
+ "unsigned long * _guids[] = {\n";
stack<StructRef> supers;
sym->chainlen = 0;
}
file << indent << "};\n\n"
- << indent << "static const __attribute__((unused)) "
+ << indent << "__attribute__((weak)) "
"::System::RunTime::VStructInfo _info = {\n"
<< indent << "\t_guids, " << sym->chainlen << ",\n"
-#if 0
- << indent << "\t_marshall, _unmarshall,\n"
-#endif
+// << indent << "\t_marshall, _unmarshall,\n"
<< indent << "};\n";
if (super)
file << '\n'
- << indent << "static " << name << " *downcast(::System::VStruct *base)\n"
+ << indent << "static __attribute__((weak)) " << name << " *downcast(::System::VStruct *base)\n"
<< indent << "{\n"
<< indent << "\tif (!base)\n"
<< indent << "\t\treturn NULL;\n\n"
output_nsdecl_begin(sym);
output_nsdecl_children(sym);
output_guid(sym->def.guid);
+ output_marshall(sym, trav_nsdecl);
output_nsdecl_end(sym);
} else {
- output_nsdecl(sym);
+ output_nsdecl_begin(sym);
+ output_nsdecl_children(sym);
+ output_marshall(sym, trav_nsdecl);
+ output_nsdecl_end(sym);
}
break;
<< indent << " int nsegs);\n\n";
#endif
- file << indent << "static const __attribute__((unused))\n"
+ file << indent << "__attribute__((weak)) __attribute__((unused))\n"
<< indent << "::System::RunTime::IFaceInfo _info = {\n"
<< indent << "\t&_guid,\n"
<< indent << "};\n";
do_extra_newline = true;
}
-void CPPFile::output_marshall(Struct *sym)
+void CPPFile::output_marshall(Struct *sym, int pass)
{
- file << indent;
-
+ switch (pass) {
+ case trav_nsdecl:
+ extra_newline();
+
+ file << indent << "int _marshall(::System::RunTime::GrowableArray<uint8_t> &buf,\n"
+ << indent << " ::System::RunTime::GrowableArray< ::System::RunTime::ID> &objlist,\n"
+ << indent << " ::System::RunTime::GrowableArray< ::System::RunTime::NewObject> &newobjlist,\n"
+ << indent << " ::System::RunTime::ParamInfoBlock::Segment *segs,\n"
+ << indent << " int nsegs);\n";
+
+ file << indent << "void _unmarshall(::System::RunTime::Array<uint8_t> buf,\n"
+ << indent << " ::System::RunTime::Array< ::System::_i_Object *> objlist,\n"
+ << indent << " ::System::RunTime::ParamInfoBlock::Segment *segs,\n"
+ << indent << " int nsegs);\n";
+
+ do_extra_newline = true;
+ break;
+ }
}
int nsegs);
::System::_i_Object *(*wrapper)(ID id);
};
+
+ struct NewObject {
+ uint32_t guid_hash[5]; // SHA-1 hash of Interface GUIDs
+ uint32_t id;
+ uint32_t reserved[3]; // must be zero
+ };
struct VStructInfo {
// List of GUIDs of the struct and its superstructs,
int (*marshall)(GrowableArray<uint8_t> &buf,
GrowableArray<ID> &objlist,
+ GrowableArray<NewObject> &newobjlist,
ParamInfoBlock::Segment *segs,
int nsegs);
void (*unmarshall)(Array<uint8_t> buf,
- Array<ID> objlist,
+ Array< ::System::_i_Object *> objlist,
ParamInfoBlock::Segment *segs,
int nsegs);
};