Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Handle struct returns. Needs some more work on memory management stuf…
…f, but basically works now. Needed a little refactor to the CStruct REPR, thanks to braino when doing it before.
  • Loading branch information
jnthn committed Nov 27, 2011
1 parent 4aade5a commit ba2dda5
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 21 deletions.
38 changes: 24 additions & 14 deletions src/6model/reprs/CStruct.c
Expand Up @@ -165,13 +165,13 @@ static void compute_allocation_strategy(PARROT_INTERP, PMC *WHAT, CStructREPRDat

/* If we have no attributes in the index mapping, then just the header. */
if (repr_data->name_to_index_mapping[0].class_key == NULL) {
repr_data->allocation_size = sizeof(CStructInstance);
repr_data->struct_size = 1; /* avoid 0-byte malloc */
}

/* Otherwise, we need to compute the allocation strategy. */
else {
/* We track the size of the body part, since that's what we want offsets into. */
INTVAL cur_size = sizeof(PMC **) + sizeof(STRING **);
/* We track the size of the struct, which is what we'll want offsets into. */
INTVAL cur_size = 0;

/* Get number of attributes and set up various counters. */
INTVAL num_attrs = VTABLE_elements(interp, flat_list);
Expand Down Expand Up @@ -229,7 +229,7 @@ static void compute_allocation_strategy(PARROT_INTERP, PMC *WHAT, CStructREPRDat

/* Finally, put computed allocation size in place; it's body size plus
* header size. Also number of markables and sentinels. */
repr_data->allocation_size = cur_size + (sizeof(CStructInstance) - sizeof(void *));
repr_data->struct_size = cur_size;
if (repr_data->initialize_slots)
repr_data->initialize_slots[cur_init_slot] = -1;
}
Expand Down Expand Up @@ -321,14 +321,13 @@ static PMC * allocate(PARROT_INTERP, STable *st) {

/* Compute allocation strategy if we've not already done so. */
CStructREPRData * repr_data = (CStructREPRData *) st->REPR_data;
if (!repr_data->allocation_size) {
if (!repr_data->struct_size) {
compute_allocation_strategy(interp, st->WHAT, repr_data);
PARROT_GC_WRITE_BARRIER(interp, st->stable_pmc);
}

/* Allocate and set up object instance. */
obj = (CStructInstance *) Parrot_gc_allocate_fixed_size_storage(interp, repr_data->allocation_size);
memset(obj, 0, repr_data->allocation_size);
obj = (CStructInstance *) Parrot_gc_allocate_fixed_size_storage(interp, sizeof(CStructInstance));
obj->common.stable = st->stable_pmc;
/* XXX allocate child str and obj arrays if needed. */

Expand All @@ -338,12 +337,19 @@ static PMC * allocate(PARROT_INTERP, STable *st) {
/* Initialize a new instance. */
static void initialize(PARROT_INTERP, STable *st, void *data) {
CStructREPRData * repr_data = (CStructREPRData *) st->REPR_data;

/* Allocate object body. */
CStructBody *body = (CStructBody *)data;
body->cstruct = mem_sys_allocate(repr_data->struct_size);
memset(body->cstruct, 0, repr_data->struct_size);

/* Initialize the slots. */
if (repr_data->initialize_slots) {
INTVAL i;
for (i = 0; repr_data->initialize_slots[i] >= 0; i++) {
INTVAL offset = repr_data->struct_offsets[repr_data->initialize_slots[i]];
STable *st = repr_data->flattened_stables[repr_data->initialize_slots[i]];
st->REPR->initialize(interp, st, (char *)data + offset);
st->REPR->initialize(interp, st, (char *)body->cstruct + offset);
}
}
}
Expand All @@ -353,7 +359,7 @@ static void copy_to(PARROT_INTERP, STable *st, void *src, void *dest) {
CStructREPRData * repr_data = (CStructREPRData *) st->REPR_data;
CStructBody *src_body = (CStructBody *)src;
CStructBody *dest_body = (CStructBody *)dest;
memcpy(dest, src, repr_data->allocation_size - sizeof(CStructInstance));
/* XXX todo */
/* XXX also need to shallow copy the obj and str arrays */
}

Expand All @@ -380,13 +386,14 @@ static PMC * get_attribute_boxed(PARROT_INTERP, STable *st, void *data, PMC *cla
}
static void * get_attribute_ref(PARROT_INTERP, STable *st, void *data, PMC *class_handle, STRING *name, INTVAL hint) {
CStructREPRData *repr_data = (CStructREPRData *)st->REPR_data;
INTVAL slot;
CStructBody *body = (CStructBody *)data;
INTVAL slot;

/* Look up slot, then offset and compute address. */
slot = hint >= 0 ? hint :
try_get_slot(interp, repr_data, class_handle, name);
if (slot >= 0)
return ((char *)data) + repr_data->struct_offsets[slot];
return ((char *)body->cstruct) + repr_data->struct_offsets[slot];

/* Otherwise, complain that the attribute doesn't exist. */
no_such_attribute(interp, "get", class_handle, name);
Expand All @@ -398,6 +405,7 @@ static void bind_attribute_boxed(PARROT_INTERP, STable *st, void *data, PMC *cla
}
static void bind_attribute_ref(PARROT_INTERP, STable *st, void *data, PMC *class_handle, STRING *name, INTVAL hint, void *value) {
CStructREPRData *repr_data = (CStructREPRData *)st->REPR_data;
CStructBody *body = (CStructBody *)data;
INTVAL slot;

/* Try to find the slot. */
Expand All @@ -406,7 +414,7 @@ static void bind_attribute_ref(PARROT_INTERP, STable *st, void *data, PMC *class
if (slot >= 0) {
STable *st = repr_data->flattened_stables[slot];
if (st)
st->REPR->copy_to(interp, st, value, (char *)data + repr_data->struct_offsets[slot]);
st->REPR->copy_to(interp, st, value, ((char *)body->cstruct) + repr_data->struct_offsets[slot]);
else
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"Can not bind by reference to non-flattened attribute '%Ss' on class '%Ss'",
Expand Down Expand Up @@ -490,14 +498,16 @@ static void gc_cleanup(PARROT_INTERP, STable *st, void *data) {
CStructBody *body = (CStructBody *)data;
if (body->child_objs)
mem_sys_free(body->child_objs);
if (body->cstruct)
mem_sys_free(body->cstruct);
}

/* This Parrot-specific addition to the API is used to free an object. */
static void gc_free(PARROT_INTERP, PMC *obj) {
CStructREPRData *repr_data = (CStructREPRData *)STABLE(obj)->REPR_data;
gc_cleanup(interp, STABLE(obj), OBJECT_BODY(obj));
if (repr_data->allocation_size && IS_CONCRETE(obj))
Parrot_gc_free_fixed_size_storage(interp, repr_data->allocation_size, PMC_data(obj));
if (IS_CONCRETE(obj))
Parrot_gc_free_fixed_size_storage(interp, sizeof(CStructInstance), PMC_data(obj));
else
mem_sys_free(PMC_data(obj));
PMC_data(obj) = NULL;
Expand Down
11 changes: 5 additions & 6 deletions src/6model/reprs/CStruct.h
Expand Up @@ -14,9 +14,9 @@ typedef struct {
* when we put them in the C structure. */
STRING **child_strs;

/* This is not an actual pointer; instead it's just a marker we can
* use to get at the start of the data that we'll actually pass off
* to C land. */
/* 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 *cstruct;
} CStructBody;

Expand All @@ -42,9 +42,8 @@ typedef struct {
/* The CStruct REPR data contains info we need to do allocations, look up
* attributes and so forth. */
typedef struct {
/* The memory allocation size for an object instance. Includes space
* for the common header and the C struct part. */
INTVAL allocation_size;
/* The size of the structure. */
INTVAL struct_size;

/* The number of attributes we have allocated slots for. Note that
* slots can vary in size. */
Expand Down
18 changes: 17 additions & 1 deletion src/ops/nqp_dyncall.ops
Expand Up @@ -212,6 +212,20 @@ make_str_result(PARROT_INTERP, PMC *type, INTVAL ret_type, char *cstring) {
return result;
}

/* Constructs a boxed result using a CStruct REPR type. */
static PMC *
make_cstruct_result(PARROT_INTERP, PMC *type, void *cstruct) {
PMC *result = type;
if (cstruct != NULL && !PMC_IS_NULL(type)) {
if (REPR(type)->ID != cs_repr_id)
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"Native call expected return type with CStruct representation, but got something else");
result = REPR(type)->allocate(interp, STABLE(type));
((CStructInstance *)PMC_data(result))->body.cstruct = cstruct;
}
return result;
}

PMC * decontainerize(PARROT_INTERP, PMC *var) {
ContainerSpec *spec = STABLE(var)->container_spec;
if (spec && IS_CONCRETE(var)) {
Expand Down Expand Up @@ -392,7 +406,7 @@ inline op nqp_native_call(out PMC, in PMC, in PMC, in PMC) :base_core {
if (!IS_CONCRETE(value))
dcArgPointer(vm, NULL);
else if (REPR(value)->ID == cs_repr_id)
dcArgPointer(vm, &((CStructInstance *)PMC_data(value))->body.cstruct);
dcArgPointer(vm, ((CStructInstance *)PMC_data(value))->body.cstruct);
else
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"Native call expected object with CStruct representation, but got something else");
Expand Down Expand Up @@ -438,6 +452,8 @@ inline op nqp_native_call(out PMC, in PMC, in PMC, in PMC) :base_core {
(char *)dcCallPointer(vm, body->entry_point));
break;
case DYNCALL_ARG_CSTRUCT:
result = make_cstruct_result(interp, $2, dcCallPointer(vm, body->entry_point));
break;
case DYNCALL_ARG_PACKEDARRAY:
case DYNCALL_ARG_CALLBACK:
/* XXX Above are all still todo. */
Expand Down

0 comments on commit ba2dda5

Please sign in to comment.