#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;
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;
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);
- typedef uint64_t GUID[2];
+ uintptr_t downcast(::System::_i_Object *obj, const GUID *new_guid);
// FIXME: use above typedef
static inline bool guids_equal(const unsigned long *guid1,
guid1[3] == guid2[3])));
}
- typedef uint32_t ID;
struct ParamInfoBlock {
uint32_t buffer_size;
uint32_t copy_size;
- ID *objlist;
- uint32_t objlist_len;
+ ID *objlist, *newobj;
+ uint32_t objlist_len, newobj_len;
uint32_t num_segments;
struct Segment {
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
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)
{