]> git.buserror.net Git - polintos/scott/priv.git/blobdiff - include/c++/orb.h
Some weak symbol usage, and some marshalling stuff.
[polintos/scott/priv.git] / include / c++ / orb.h
index 31348f2227a3f6680ac31e8ce281c464468ea32b..1f1a3e6f6588586d69caec87fd0976ff6571c783 100644 (file)
@@ -4,6 +4,10 @@
 #include <stdint.h>
 #include <stddef.h>
 #include <string.h>
+#include <limits.h>
+
+#include <lowlevel/barriers.h>
+#include <lowlevel/bitops.h>
 
 namespace System {
        struct _i_Object;
@@ -125,6 +129,71 @@ namespace System {
                                return new_arr;
                        }
                };
+               
+               template<typename T>
+               struct GrowableArray : public MutableArray<T> {
+                       using MutableArray<T>::ptr;
+                       using MutableArray<T>::count;
+                       size_t bufsize;
+                       
+                       GrowableArray()
+                       {
+                               bufsize = 0;
+                       }
+                       
+                       GrowableArray(NullArray na) : MutableArray<T>(na)
+                       {
+                               bufsize = 0;
+                       }
+                       
+                       GrowableArray(T *PTR, size_t COUNT) : MutableArray<T>(PTR, COUNT)
+                       {
+                               bufsize = COUNT;
+                       }
+                       
+                       GrowableArray(T *PTR, size_t COUNT, size_t BUFSIZE) :
+                       MutableArray<T>(PTR, COUNT)
+                       {
+                               bufsize = BUFSIZE;
+                       }
+                       
+                       GrowableArray(MutableArray<T> &ma) : MutableArray<T>(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<typename T> 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<ID> 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<uint8_t> &buf,
+                                       GrowableArray<ID> &objlist,
+                                       GrowableArray<NewObject> &newobjlist,
+                                       ParamInfoBlock::Segment *segs,
+                                       int nsegs);
+                       void (*unmarshall)(Array<uint8_t> 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