#include <stdint.h>
#include <stddef.h>
#include <string.h>
+#include <limits.h>
+
+#include <lowlevel/barriers.h>
+#include <lowlevel/bitops.h>
+
+#include <util/array.h>
namespace System {
struct _i_Object;
}
namespace RunTime {
+ using namespace ::Util::Arrays;
+
class ORBMM {
- void *priv;
+ static void *priv;
public:
- class AllocGroup {
- friend class ORBMM;
- };
-
typedef ::System::Mem::Region Region;
- ORBMM();
-
- void *alloc(size_t size, AllocGroup *group = NULL);
-
- void retain(Region region);
- void release(Region region);
- void super_retain(Region region);
- void super_release(Region region);
- AllocGroup *create_group();
- void destroy_group(AllocGroup *group);
- void *add_region(Region region);
+ static void *alloc(size_t size, int refs = 1);
+ static void retain(void *ptr, int refs = 1);
+ static void release(void *ptr, int refs = 1);
+ static void add_region(Region region, bool unmap_orig, int refs = 1);
};
- extern ORBMM *orbmm;
-
- // FIXME: should be an IDL exception
- struct ArrayException
- {
+ struct IFaceInfo;
+ typedef uint32_t ID;
+
+ struct IFaceTable {
+ const IFaceInfo *info;
+ const ptrdiff_t offset;
};
- class NullArray {
+ union GUID {
+ unsigned char c[16];
+ unsigned long l[16 / sizeof(unsigned long)];
};
-
- static const NullArray nullarray = {};
-
- template<typename T> struct MutableArray {
- T *ptr;
- size_t count;
-
- bool valid_index(size_t index)
- {
- return index >= 0 && index < count;
- }
-
- T &operator[](size_t index)
- {
-#ifndef POLINTOS_NO_ARRAY_BOUNDS_CHECK
- if (!valid_index(index))
- throw ArrayException();
-#endif
-
- return ptr[index];
- }
-
- MutableArray()
- {
- ptr = NULL;
- count = 0;
- }
-
- MutableArray(NullArray na)
- {
- ptr = NULL;
- count = 0;
- }
-
- MutableArray(T *PTR, size_t COUNT)
- {
- ptr = PTR;
- count = COUNT;
- }
-
- MutableArray &slice_nocheck(size_t first, size_t newcount)
- {
- MutableArray ret;
- ret.ptr = ptr + first;
- ret.count = newcount;
- return ret;
- }
- MutableArray &slice_nocheck(size_t first)
- {
- MutableArray ret;
- ret.ptr = ptr + first;
- ret.count = count - first;
- return ret;
- }
+ uintptr_t downcast(::System::_i_Object *obj, const GUID *new_guid);
- MutableArray &slice(size_t first, size_t count)
- {
-#ifndef POLINTOS_NO_ARRAY_BOUNDS_CHECK
- if (!valid_index(first) || !valid_index(first + count - 1))
- throw ArrayException();
-#endif
-
- return slice_nocheck(first, count);
- }
+ // FIXME: use above typedef
+ static inline bool guids_equal(const unsigned long *guid1,
+ const unsigned long *guid2)
+ {
+ return (guid1[0] == guid2[0] &&
+ guid1[1] == guid2[1] &&
+ (sizeof(long) == 8 ||
+ (guid1[2] == guid2[2] &&
+ guid1[3] == guid2[3])));
+ }
+
+ struct ParamInfoBlock {
+ uint32_t buffer_size;
+ uint32_t copy_size;
+ ID *objlist, *newobj;
+ uint32_t objlist_len, newobj_len;
+ uint32_t num_segments;
- MutableArray &slice(size_t first)
- {
-#ifndef POLINTOS_NO_ARRAY_BOUNDS_CHECK
- if (!valid_index(first))
- throw ArrayException();
-#endif
+ struct Segment {
+ uint8_t *ptr;
+ uintptr_t len;
+ uintptr_t flags;
+ uintptr_t reserved;
- return slice_nocheck(first);
- }
-
- MutableArray copy()
- {
- MutableArray new_arr;
- new_arr.ptr = new(orbmm) T[count];
- new_arr.count = count;
- memcpy(new_arr.ptr, ptr, count);
- return new_arr;
- }
+ enum {
+ In = 1,
+ Out = 2,
+ Inline = 4,
+ Copy = 8
+ };
+ } segments[0];
};
-
- template<typename T> struct Array {
- const T *ptr;
- size_t count;
- bool valid_index(size_t index)
- {
- return index >= 0 && index < count;
- }
-
- const T &operator[](size_t index)
- {
-#ifndef POLINTOS_NO_ARRAY_BOUNDS_CHECK
- if (!valid_index(index))
- throw ArrayException();
-#endif
+ struct Segment0 {
+ enum {
+ InvokeMethod = 0,
+ GetIFaces = 1,
+ ReturnIFaces = 2,
+ };
- return ptr[index];
- }
-
- Array()
- {
- ptr = NULL;
- count = 0;
- }
-
- Array(NullArray na)
- {
- ptr = NULL;
- count = 0;
- }
-
- Array(const T *PTR, size_t COUNT)
- {
- ptr = PTR;
- count = COUNT;
- }
-
- Array(MutableArray<T> ma)
- {
- ptr = ma.ptr;
- count = ma.count;
- }
-
- MutableArray<T> constcast()
- {
- MutableArray<T> ma;
- ma.ptr = const_cast<T>(ptr);
- ma.count = count;
- return ma;
- }
-
- Array &slice_nocheck(size_t first, size_t newcount)
- {
- Array ret;
- ret.ptr = ptr + first;
- ret.count = newcount;
- return ret;
- }
-
- Array &slice_nocheck(size_t first)
- {
- Array ret;
- ret.ptr = ptr + first;
- ret.count = count - first;
- return ret;
- }
-
- Array &slice(size_t first, size_t count)
- {
-#ifndef POLINTOS_NO_ARRAY_BOUNDS_CHECK
- if (!valid_index(first) || !valid_index(first + count - 1))
- throw ArrayException();
-#endif
+ union {
+ struct {
+ uint8_t opcode;
+ };
- return slice_nocheck(first, count);
- }
-
- Array &slice(size_t first)
- {
-#ifndef POLINTOS_NO_ARRAY_BOUNDS_CHECK
- if (!valid_index(first))
- throw ArrayException();
-#endif
-
- return slice_nocheck(first);
- }
+ unsigned long pad;
+ };
+ };
- MutableArray<T> copy()
- {
- MutableArray<T> new_arr;
- new_arr.ptr = new(orbmm) T[count];
- new_arr.count = count;
- memcpy(new_arr.ptr, ptr, count);
- return new_arr;
- }
+ struct InvokeMethod {
+ Segment0 seg0;
+ uint32_t iface;
+ uint32_t method;
+ uint8_t args[0];
};
-
- static inline Array<uint8_t> countarray(const char *ptr)
- {
- Array<uint8_t> ret;
- ret.ptr = reinterpret_cast<const uint8_t *>(ptr);
- ret.count = strlen(ptr);
- return ret;
- }
-
- static inline MutableArray<uint8_t> countarray(char *ptr)
- {
- MutableArray<uint8_t> ret;
- ret.ptr = reinterpret_cast<uint8_t *>(ptr);
- ret.count = strlen(ptr);
- return ret;
- }
- struct IFaceTable {
- const unsigned long *const guid;
- const ptrdiff_t offset;
+ union Message {
+ Segment0 seg0;
+ InvokeMethod invoke;
+ };
+
+ struct IFaceInfo {
+ const GUID *guid;
+ void (*invoke)(Array<ID, ORBMM> 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 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
// Length of inheritance chain; 1 for System.VStruct
const int chainlen;
+
+ int (*marshall)(MarshCtx &ctx);
+ void (*unmarshall)(MarshCtx &ctx);
};
-
- uintptr_t downcast(::System::_i_Object *obj,
- const unsigned long *new_guid);
- static inline bool guids_equal(const unsigned long *guid1,
- const unsigned long *guid2)
- {
- return (guid1[0] == guid2[0] &&
- guid1[1] == guid2[1] &&
- (sizeof(long) == 8 ||
- (guid1[2] == guid2[2] &&
- 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 *objlist_ptr;
- uintptr_t objlist_len;
- uintptr_t num_segments;
+ 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();
- struct Segment {
- void *ptr;
- uintptr_t len;
- uintptr_t flags;
- uintptr_t reserved;
- } segments[0];
- };
- }
+ static inline bool in_kernel()
+ {
+#ifdef _KERNEL
+ return true;
+#else
+ return false;
+#endif
+ }
+
+ }
+ };
}
-inline void *operator new(size_t len, ::System::RunTime::ORBMM *orbmm,
- ::System::RunTime::ORBMM::AllocGroup *group = NULL)
+inline void *operator new(size_t len, ::System::RunTime::ORBMM orbmm,
+ int refs = 1)
{
- return orbmm->alloc(len, group);
+ return ::System::RunTime::ORBMM::alloc(len, refs);
}
-inline void *operator new[](size_t len, ::System::RunTime::ORBMM *orbmm,
- ::System::RunTime::ORBMM::AllocGroup *group = NULL)
+inline void *operator new[](size_t len, ::System::RunTime::ORBMM orbmm,
+ int refs = 1)
{
- return orbmm->alloc(len, group);
+ return ::System::RunTime::ORBMM::alloc(len, refs);
}
// This is a macro rather than an inline template function so that the
//
// To throw an IDL exception of type Foo, do this:
// throw_idl(Foo, args, to, foo);
-//
-// FIXME: Instead, maybe a static throw method with noinline and
-// builtin_return_address.
#ifndef POLINTOS_NO_THROW_IDL
#define throw_idl(T, args...) do { \
throw T(NULL, NULL, \
- new(::System::RunTime::orbmm) \
+ new(::System::RunTime::ORBMM()) \
::System::Exceptions::NativeCodeExceptionOriginInfo \
- (::System::RunTime::get_pc()), \
- _KERNEL ? 1 : 0, ##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) \
+ throw T(new(::System::RunTime::ORBMM()) typeof(oldex)(oldex), NULL, \
+ new(::System::RunTime::ORBMM()) \
::System::Exceptions::NativeCodeExceptionOriginInfo \
- (::System::RunTime::get_pc()), \
- _KERNEL ? 1 : 0, ##args); \
+ (::System::RunTime::Priv::get_pc()), \
+ ::System::RunTime::Priv::in_kernel(), ##args); \
} while (0)
#endif