Skip to content

Commit

Permalink
reapply all commits for C++ support
Browse files Browse the repository at this point in the history
  • Loading branch information
FROGGS committed Mar 15, 2015
1 parent e39a7d7 commit 6345e59
Show file tree
Hide file tree
Showing 8 changed files with 957 additions and 2 deletions.
2 changes: 2 additions & 0 deletions build/Makefile.in
Expand Up @@ -154,6 +154,7 @@ OBJECTS = src/core/callsite@obj@ \
src/6model/reprs/ConcBlockingQueue@obj@ \
src/6model/reprs/MVMAsyncTask@obj@ \
src/6model/reprs/MVMNull@obj@ \
src/6model/reprs/CPPStruct@obj@ \
src/6model/reprs/NativeRef@obj@ \
src/6model/6model@obj@ \
src/6model/bootstrap@obj@ \
Expand Down Expand Up @@ -288,6 +289,7 @@ HEADERS = src/moar.h \
src/6model/reprs/ConcBlockingQueue.h \
src/6model/reprs/MVMAsyncTask.h \
src/6model/reprs/MVMNull.h \
src/6model/reprs/CPPStruct.h \
src/6model/reprs/NativeRef.h \
src/6model/sc.h \
src/mast/compiler.h \
Expand Down
1 change: 1 addition & 0 deletions src/6model/reprs.c
Expand Up @@ -217,6 +217,7 @@ void MVM_repr_initialize_registry(MVMThreadContext *tc) {
register_core_repr(ConcBlockingQueue);
register_core_repr(AsyncTask);
register_core_repr(Null);
register_core_repr(CPPStruct);
register_core_repr(NativeRef);

tc->instance->num_reprs = MVM_REPR_CORE_COUNT;
Expand Down
6 changes: 4 additions & 2 deletions src/6model/reprs.h
Expand Up @@ -38,6 +38,7 @@
#include "6model/reprs/ConcBlockingQueue.h"
#include "6model/reprs/MVMAsyncTask.h"
#include "6model/reprs/MVMNull.h"
#include "6model/reprs/CPPStruct.h"
#include "6model/reprs/NativeRef.h"

/* REPR related functions. */
Expand Down Expand Up @@ -87,9 +88,10 @@ const MVMREPROps * MVM_repr_get_by_name(MVMThreadContext *tc, MVMString *name);
#define MVM_REPR_ID_ConcBlockingQueue 36
#define MVM_REPR_ID_MVMAsyncTask 37
#define MVM_REPR_ID_MVMNull 38
#define MVM_REPR_ID_NativeRef 39
#define MVM_REPR_ID_MVMCPPStruct 39
#define MVM_REPR_ID_NativeRef 40

#define MVM_REPR_CORE_COUNT 40
#define MVM_REPR_CORE_COUNT 41
#define MVM_REPR_MAX_COUNT 64

/* Default attribute functions for a REPR that lacks them. */
Expand Down
763 changes: 763 additions & 0 deletions src/6model/reprs/CPPStruct.c

Large diffs are not rendered by default.

83 changes: 83 additions & 0 deletions src/6model/reprs/CPPStruct.h
@@ -0,0 +1,83 @@
/* Attribute location flags. */
#define MVM_CPPSTRUCT_ATTR_IN_STRUCT 0
#define MVM_CPPSTRUCT_ATTR_CSTRUCT 1
#define MVM_CPPSTRUCT_ATTR_CARRAY 2
#define MVM_CPPSTRUCT_ATTR_CPTR 3
#define MVM_CPPSTRUCT_ATTR_STRING 4
#define MVM_CPPSTRUCT_ATTR_CPPSTRUCT 5
#define MVM_CPPSTRUCT_ATTR_MASK 7

/* Bits to shift a slot position to make room for MVM_CPPSTRUCT_ATTR_*. */
#define MVM_CPPSTRUCT_ATTR_SHIFT 3

/* The CPPStruct representation maintains a chunk of memory that it can
* always pass off to C land. If we in turn embed any strings, pointers
* to other CPPStruct REPR objects and so forth, we need to both keep the
* C-friendly bit of memory and a copy to the GC-able, 6model objects in
* sync. */
struct MVMCPPStructBody {
/* GC-marked objects that our C structure points into. */
MVMObject **child_objs;

/* Pointer to the actual C structure memory; we don't inline it
* directly in the body, since it doesn't work so well if we get
* something returned and are wrapping it. */
void *cppstruct;
};

struct MVMCPPStruct {
MVMObject common;
MVMCPPStructBody body;
};

/* This is used in the name to class mapping. */
struct MVMCPPStructNameMap {
MVMObject *class_key;
MVMObject *name_map;
};

/* The CPPStruct REPR data contains info we need to do allocations, look up
* attributes and so forth. */
struct MVMCPPStructREPRData {
/* The size of the structure. */
MVMint32 struct_size;

/* The number of attributes we have allocated slots for. Note that
* slots can vary in size. */
MVMint32 num_attributes;

/* Number of child objects we store. */
MVMint32 num_child_objs;

/* Lower bits are flags indicating what kind of attribute we have;
* whether it's one that is just a simple value that we can always
* access directly in the C struct body, or a more complex one that
* we need to maintain in the C struct and in the GC-able list. Upper
* bits say where to find it. */
MVMint32 *attribute_locations;

/* Maps attribute position numbers to their location in the C struct.
* Note that this will not be the only place we need to update for
* any reference type. */
MVMint32 *struct_offsets;

/* If the attribute was actually flattened in to this object from another
* representation, this is the s-table of the type of that attribute. NULL
* for attributes that are reference types. */
MVMSTable **flattened_stables;

/* For reference type members, we cache the relevant type objects.
* Flattened types have NULL here. */
MVMObject **member_types;

/* A table mapping attribute names to indexes (which can then be looked
* up in the offset table). Uses a final null entry as a sentinel. */
MVMCPPStructNameMap *name_to_index_mapping;

/* Slots holding flattened objects that need another REPR to initialize
* them; terminated with -1. */
MVMint32 *initialize_slots;
};

/* Initializes the CPPStruct REPR. */
const MVMREPROps * MVMCPPStruct_initialize(MVMThreadContext *tc);
98 changes: 98 additions & 0 deletions src/core/nativecall.c
Expand Up @@ -54,6 +54,8 @@ static MVMint16 get_arg_type(MVMThreadContext *tc, MVMObject *info, MVMint16 is_
result = MVM_NATIVECALL_ARG_UTF16STR | get_str_free_flag(tc, info);
else if (strcmp(ctypename, "cstruct") == 0)
result = MVM_NATIVECALL_ARG_CSTRUCT;
else if (strcmp(ctypename, "cppstruct") == 0)
result = MVM_NATIVECALL_ARG_CPPSTRUCT;
else if (strcmp(ctypename, "cpointer") == 0)
result = MVM_NATIVECALL_ARG_CPOINTER;
else if (strcmp(ctypename, "carray") == 0)
Expand All @@ -77,6 +79,10 @@ static MVMint16 get_calling_convention(MVMThreadContext *tc, MVMString *name) {
result = DC_CALL_C_X86_CDECL;
else if (strcmp(cname, "stdcall") == 0)
result = DC_CALL_C_X86_WIN32_STD;
else if (strcmp(cname, "thisgnu") == 0)
result = DC_CALL_C_X86_WIN32_THIS_GNU;
else if (strcmp(cname, "thisms") == 0)
result = DC_CALL_C_X86_WIN32_THIS_MS;
else if (strcmp(cname, "stdcall") == 0)
result = DC_CALL_C_X64_WIN64;
else
Expand Down Expand Up @@ -174,6 +180,21 @@ MVMObject * MVM_nativecall_make_cstruct(MVMThreadContext *tc, MVMObject *type, v
return result;
}

MVMObject * MVM_nativecall_make_cppstruct(MVMThreadContext *tc, MVMObject *type, void *cppstruct) {
MVMObject *result = type;
if (cppstruct && type) {
MVMCPPStructREPRData *repr_data = (MVMCPPStructREPRData *)STABLE(type)->REPR_data;
if (REPR(type)->ID != MVM_REPR_ID_MVMCPPStruct)
MVM_exception_throw_adhoc(tc,
"Native call expected return type with CPPStruct representation, but got a %s", REPR(type)->name);
result = REPR(type)->allocate(tc, STABLE(type));
((MVMCPPStruct *)result)->body.cppstruct = cppstruct;
if (repr_data->num_child_objs)
((MVMCPPStruct *)result)->body.child_objs = MVM_calloc(repr_data->num_child_objs, sizeof(MVMObject *));
}
return result;
}

/* Constructs a boxed result using a CPointer REPR type. */
MVMObject * MVM_nativecall_make_cpointer(MVMThreadContext *tc, MVMObject *type, void *ptr) {
MVMObject *result = type;
Expand Down Expand Up @@ -272,6 +293,16 @@ static void * unmarshal_cstruct(MVMThreadContext *tc, MVMObject *value) {
"Native call expected return type with CStruct representation, but got a %s", REPR(value)->name);
}

static void * unmarshal_cppstruct(MVMThreadContext *tc, MVMObject *value) {
if (!IS_CONCRETE(value))
return NULL;
else if (REPR(value)->ID == MVM_REPR_ID_MVMCPPStruct)
return ((MVMCPPStruct *)value)->body.cppstruct;
else
MVM_exception_throw_adhoc(tc,
"Native call expected return type with CPPStruct representation, but got a %s", REPR(value)->name);
}

static void * unmarshal_cpointer(MVMThreadContext *tc, MVMObject *value) {
if (!IS_CONCRETE(value))
return NULL;
Expand Down Expand Up @@ -657,6 +688,7 @@ MVMObject * MVM_nativecall_invoke(MVMThreadContext *tc, MVMObject *res_type,
MVMint16 *arg_types = body->arg_types;
MVMint16 ret_type = body->ret_type;
void *entry_point = body->entry_point;
void *ptr = NULL;

/* Create and set up call VM. */
DCCallVM *vm = dcNewCallVM(8192);
Expand Down Expand Up @@ -705,6 +737,21 @@ MVMObject * MVM_nativecall_invoke(MVMThreadContext *tc, MVMObject *res_type,
case MVM_NATIVECALL_ARG_CSTRUCT:
dcArgPointer(vm, unmarshal_cstruct(tc, value));
break;
case MVM_NATIVECALL_ARG_CPPSTRUCT: {
/* We need to allocate the struct (THIS) for C++ constructor before passing it along. */
if (i == 0 && !IS_CONCRETE(value)) {
MVMCPPStructREPRData *repr_data = (MVMCPPStructREPRData *)STABLE(res_type)->REPR_data;
/* Allocate a full byte aligned area where the C++ structure fits into. */
ptr = MVM_malloc(repr_data->struct_size > 0 ? repr_data->struct_size : 1);
result = MVM_nativecall_make_cppstruct(tc, res_type, ptr);

dcArgPointer(vm, ptr);
}
else {
dcArgPointer(vm, unmarshal_cppstruct(tc, value));
}
}
break;
case MVM_NATIVECALL_ARG_CPOINTER:
dcArgPointer(vm, unmarshal_cpointer(tc, value));
break;
Expand Down Expand Up @@ -760,6 +807,9 @@ MVMObject * MVM_nativecall_invoke(MVMThreadContext *tc, MVMObject *res_type,
case MVM_NATIVECALL_ARG_CSTRUCT:
result = MVM_nativecall_make_cstruct(tc, res_type, dcCallPointer(vm, body->entry_point));
break;
case MVM_NATIVECALL_ARG_CPPSTRUCT:
result = MVM_nativecall_make_cppstruct(tc, res_type, dcCallPointer(vm, body->entry_point));
break;
case MVM_NATIVECALL_ARG_CPOINTER:
result = MVM_nativecall_make_cpointer(tc, res_type, dcCallPointer(vm, body->entry_point));
break;
Expand Down Expand Up @@ -958,6 +1008,8 @@ MVMObject * MVM_nativecall_cast(MVMThreadContext *tc, MVMObject *target_spec, MV
MVMint64 MVM_nativecall_sizeof(MVMThreadContext *tc, MVMObject *obj) {
if (REPR(obj)->ID == MVM_REPR_ID_MVMCStruct)
return ((MVMCStructREPRData *)STABLE(obj)->REPR_data)->struct_size;
else if (REPR(obj)->ID == MVM_REPR_ID_MVMCPPStruct)
return ((MVMCPPStructREPRData *)STABLE(obj)->REPR_data)->struct_size;
else if (REPR(obj)->ID == MVM_REPR_ID_P6int)
return ((MVMP6intREPRData *)STABLE(obj)->REPR_data)->bits / 8;
else if (REPR(obj)->ID == MVM_REPR_ID_P6num)
Expand Down Expand Up @@ -1069,6 +1121,52 @@ void MVM_nativecall_refresh(MVMThreadContext *tc, MVMObject *cthingy) {
objptr = NULL;
}

if (objptr != cptr)
body->child_objs[slot] = NULL;
else
MVM_nativecall_refresh(tc, body->child_objs[slot]);
}
}
else if (REPR(cthingy)->ID == MVM_REPR_ID_MVMCPPStruct) {
MVMCPPStructBody *body = (MVMCPPStructBody *)OBJECT_BODY(cthingy);
MVMCPPStructREPRData *repr_data = (MVMCPPStructREPRData *)STABLE(cthingy)->REPR_data;
char *storage = (char *) body->cppstruct;
MVMint64 i;

for (i = 0; i < repr_data->num_attributes; i++) {
MVMint32 kind = repr_data->attribute_locations[i] & MVM_CPPSTRUCT_ATTR_MASK;
MVMint32 slot = repr_data->attribute_locations[i] >> MVM_CPPSTRUCT_ATTR_SHIFT;
void *cptr; /* The pointer in the C storage. */
void *objptr; /* The pointer in the object representing the C object. */

if (kind == MVM_CPPSTRUCT_ATTR_IN_STRUCT || !body->child_objs[slot])
continue;

cptr = *((void **)(storage + repr_data->struct_offsets[i]));
if (IS_CONCRETE(body->child_objs[slot])) {
switch (kind) {
case MVM_CPPSTRUCT_ATTR_CARRAY:
objptr = ((MVMCArrayBody *)OBJECT_BODY(body->child_objs[slot]))->storage;
break;
case MVM_CPPSTRUCT_ATTR_CPTR:
objptr = ((MVMCPointerBody *)OBJECT_BODY(body->child_objs[slot]))->ptr;
break;
case MVM_CPPSTRUCT_ATTR_CSTRUCT:
objptr = (MVMCStructBody *)OBJECT_BODY(body->child_objs[slot]);
break;
case MVM_CPPSTRUCT_ATTR_STRING:
objptr = NULL;
break;
default:
MVM_exception_throw_adhoc(tc,
"Fatal error: bad kind (%d) in CPPStruct write barrier",
kind);
}
}
else {
objptr = NULL;
}

if (objptr != cptr)
body->child_objs[slot] = NULL;
else
Expand Down
2 changes: 2 additions & 0 deletions src/core/nativecall.h
Expand Up @@ -15,6 +15,7 @@
#define MVM_NATIVECALL_ARG_CALLBACK 26
#define MVM_NATIVECALL_ARG_CPOINTER 28
#define MVM_NATIVECALL_ARG_VMARRAY 30
#define MVM_NATIVECALL_ARG_CPPSTRUCT 32
#define MVM_NATIVECALL_ARG_TYPE_MASK 62

/* Flag for whether we should free a string after passing it or not. */
Expand Down Expand Up @@ -77,5 +78,6 @@ MVMObject * MVM_nativecall_cast(MVMThreadContext *tc, MVMObject *target_spec,
MVMint64 MVM_nativecall_sizeof(MVMThreadContext *tc, MVMObject *obj);
void MVM_nativecall_refresh(MVMThreadContext *tc, MVMObject *cthingy);
MVMObject * MVM_nativecall_make_cstruct(MVMThreadContext *tc, MVMObject *type, void *cstruct);
MVMObject * MVM_nativecall_make_cppstruct(MVMThreadContext *tc, MVMObject *type, void *cppstruct);
MVMObject * MVM_nativecall_make_cpointer(MVMThreadContext *tc, MVMObject *type, void *ptr);
MVMObject * MVM_nativecall_make_carray(MVMThreadContext *tc, MVMObject *type, void *carray);
4 changes: 4 additions & 0 deletions src/types.h
Expand Up @@ -88,6 +88,10 @@ typedef struct MVMCStruct MVMCStruct;
typedef struct MVMCStructBody MVMCStructBody;
typedef struct MVMCStructNameMap MVMCStructNameMap;
typedef struct MVMCStructREPRData MVMCStructREPRData;
typedef struct MVMCPPStruct MVMCPPStruct;
typedef struct MVMCPPStructBody MVMCPPStructBody;
typedef struct MVMCPPStructNameMap MVMCPPStructNameMap;
typedef struct MVMCPPStructREPRData MVMCPPStructREPRData;
typedef struct MVMMultiCache MVMMultiCache;
typedef struct MVMMultiCacheBody MVMMultiCacheBody;
typedef struct MVMMultiArityCache MVMMultiArityCache;
Expand Down

0 comments on commit 6345e59

Please sign in to comment.