X-Git-Url: http://git.buserror.net/cgi-bin/gitweb.cgi?p=polintos%2Fscott%2Fpriv.git;a=blobdiff_plain;f=include%2Fc%2B%2B%2Forb.h;h=1f1a3e6f6588586d69caec87fd0976ff6571c783;hp=31348f2227a3f6680ac31e8ce281c464468ea32b;hb=b024710fe2b60cd4a42a8993b61333d6cdb56ca3;hpb=e4560eb81e14ff6ce67752591ea63ad58bfc45be diff --git a/include/c++/orb.h b/include/c++/orb.h index 31348f2..1f1a3e6 100644 --- a/include/c++/orb.h +++ b/include/c++/orb.h @@ -4,6 +4,10 @@ #include #include #include +#include + +#include +#include namespace System { struct _i_Object; @@ -125,6 +129,71 @@ namespace System { return new_arr; } }; + + template + struct GrowableArray : public MutableArray { + using MutableArray::ptr; + using MutableArray::count; + size_t bufsize; + + GrowableArray() + { + bufsize = 0; + } + + GrowableArray(NullArray na) : MutableArray(na) + { + bufsize = 0; + } + + GrowableArray(T *PTR, size_t COUNT) : MutableArray(PTR, COUNT) + { + bufsize = COUNT; + } + + GrowableArray(T *PTR, size_t COUNT, size_t BUFSIZE) : + MutableArray(PTR, COUNT) + { + bufsize = BUFSIZE; + } + + GrowableArray(MutableArray &ma) : MutableArray(ma) + { + bufsize = count; + } + + void grow(size_t newsize) + { + if (newsize <= bufsize) + return; + + T *oldptr = ptr; + T *newptr = new(orbmm) T[newsize]; + memcpy(newptr, ptr, count * sizeof(T)); + ptr = newptr; + ll_smp_membar_store_after_store(); + bufsize = newsize; + // FIXME: Should release imply membar? + ll_smp_membar_any_after_store(); + orbmm->release(oldptr); + } + + // Caller must sync against all writers. + void append(T *newptr, size_t len, size_t max = ULONG_MAX) + { + 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)); + count += len; + } + }; template struct Array { const T *ptr; @@ -239,26 +308,22 @@ namespace System { return ret; } + struct IFaceInfo; + typedef uint32_t ID; + struct IFaceTable { - const unsigned long *const guid; + const IFaceInfo *info; const ptrdiff_t offset; }; - struct VStructInfo { - // List of GUIDs of the struct and its superstructs, - // starting with System.VStruct and ending with - // the concrete struct. - - const unsigned long *const *const guids; - - // Length of inheritance chain; 1 for System.VStruct - - const int chainlen; + union GUID { + unsigned char c[16]; + unsigned long l[]; }; - - uintptr_t downcast(::System::_i_Object *obj, - const unsigned long *new_guid); + uintptr_t downcast(::System::_i_Object *obj, const GUID *new_guid); + + // FIXME: use above typedef static inline bool guids_equal(const unsigned long *guid1, const unsigned long *guid2) { @@ -269,37 +334,108 @@ namespace System { guid1[3] == guid2[3]))); } - // 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 - // than a function call. OPT: put this in lowlevel-lib, so that - // architectures can provide a faster version. - - unsigned long get_pc(); - struct ParamInfoBlock { - uintptr_t buffer_size; - uintptr_t copy_size; - uintptr_t *objlist_ptr; - uintptr_t objlist_len; - uintptr_t num_segments; + uint32_t buffer_size; + uint32_t copy_size; + ID *objlist, *newobj; + uint32_t objlist_len, newobj_len; + uint32_t num_segments; struct Segment { - void *ptr; + uint8_t *ptr; uintptr_t len; uintptr_t flags; uintptr_t reserved; + + enum { + In = 1, + Out = 2, + Inline = 4, + Copy = 8 + }; } segments[0]; }; - } - - namespace Priv { - bool in_kernel() - { + + struct Segment0 { + enum { + InvokeMethod = 0, + GetIFaces = 1, + ReturnIFaces = 2, + }; + + union { + struct { + uint8_t opcode; + }; + + unsigned long pad; + }; + }; + + struct InvokeMethod { + Segment0 seg0; + uint32_t iface; + uint32_t method; + uint8_t args[0]; + }; + + union Message { + Segment0 seg0; + InvokeMethod invoke; + }; + + struct IFaceInfo { + const GUID *guid; + void (*invoke)(Array objlist, + ParamInfoBlock::Segment *segs, + 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, + // starting with System.VStruct and ending with + // the concrete struct. + + const unsigned long *const *const guids; + + // Length of inheritance chain; 1 for System.VStruct + + const int chainlen; + + int (*marshall)(GrowableArray &buf, + GrowableArray &objlist, + GrowableArray &newobjlist, + ParamInfoBlock::Segment *segs, + int nsegs); + void (*unmarshall)(Array buf, + Array< ::System::_i_Object *> objlist, + ParamInfoBlock::Segment *segs, + int nsegs); + }; + + 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 + // than a function call. OPT: put this in lowlevel-lib, so that + // architectures can provide a faster version. + + unsigned long get_pc(); + + static inline bool in_kernel() + { #ifdef _KERNEL - return true; + return true; #else - return false; + return false; #endif + } } }; } @@ -316,6 +452,7 @@ inline void *operator new[](size_t len, ::System::RunTime::ORBMM *orbmm, return orbmm->alloc(len, refs); } +// FIXME: This isn't safe on anything with a descructor. inline void operator delete(void *ptr, ::System::RunTime::ORBMM *orbmm, int refs = 1) { @@ -341,16 +478,16 @@ inline void operator delete[](void *ptr, ::System::RunTime::ORBMM *orbmm, throw T(NULL, NULL, \ new(::System::RunTime::orbmm) \ ::System::Exceptions::NativeCodeExceptionOriginInfo \ - (::System::RunTime::get_pc()), \ - ::System::Priv::in_kernel(), ##args); \ + (::System::RunTime::Priv::get_pc()), \ + ::System::RunTime::Priv::in_kernel(), ##args); \ } while (0) #define rethrow_idl(oldex, T, args...) do { \ throw T(new(::System::RunTime::orbmm) typeof(oldex)(oldex), NULL, \ new(::System::RunTime::orbmm) \ ::System::Exceptions::NativeCodeExceptionOriginInfo \ - (::System::RunTime::get_pc()), \ - ::System::Priv::in_kernel(), ##args); \ + (::System::RunTime::Priv::get_pc()), \ + ::System::RunTime::Priv::in_kernel(), ##args); \ } while (0) #endif