Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Start replacing container spec approach.
This is the minimum needed to get NQP to build and pass its tests again
with the data structure updates. Still needs some more infrastructure
before we can start updating Rakudo to use this new approach.
  • Loading branch information
jnthn committed Mar 19, 2013
1 parent 3c65140 commit 11b1430
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 114 deletions.
25 changes: 15 additions & 10 deletions src/6model/serialization.c
Expand Up @@ -19,7 +19,7 @@

/* Version of the serialization format that we are currently at and lowest
* version we support. */
#define CURRENT_VERSION 3
#define CURRENT_VERSION 4
#define MIN_VERSION 1

/* Various sizes (in bytes). */
Expand Down Expand Up @@ -748,10 +748,11 @@ static void serialize_stable(PARROT_INTERP, SerializationWriter *writer, PMC *st
/* Container spec. */
write_int_func(interp, writer, st->container_spec != NULL);
if (st->container_spec) {
write_ref_func(interp, writer, st->container_spec->value_slot.class_handle);
write_str_func(interp, writer, st->container_spec->value_slot.attr_name);
write_int_func(interp, writer, st->container_spec->value_slot.hint);
write_ref_func(interp, writer, st->container_spec->fetch_method);
/* Write container spec name. */
write_str_func(interp, writer, st->container_spec->name);

/* Give container spec a chance to serialize any data it wishes. */
st->container_spec->serialize(interp, st, writer);
}

/* If the REPR has a function to serialize representation data, call it. */
Expand Down Expand Up @@ -1617,11 +1618,15 @@ static void deserialize_stable(PARROT_INTERP, SerializationReader *reader, INTVA

/* Container spec. */
if (read_int_func(interp, reader)) {
st->container_spec = (ContainerSpec *)mem_sys_allocate(sizeof(ContainerSpec));
st->container_spec->value_slot.class_handle = read_ref_func(interp, reader);
st->container_spec->value_slot.attr_name = read_str_func(interp, reader);
st->container_spec->value_slot.hint = read_int_func(interp, reader);
st->container_spec->fetch_method = read_ref_func(interp, reader);
/* Depends on version. If before 4, we don't try to read it. */
if (reader->root.version < 4)
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"Unable to deserialize old container spec format");

/* Otherwise, resolve the container spec by name and get it
* set up. */
read_str_func(interp, reader);
/* XXX TODO: The rest of this. */
}

/* Mark it as being in the SC we're currently deserializing. */
Expand Down
23 changes: 2 additions & 21 deletions src/6model/sixmodelobject.c
Expand Up @@ -183,26 +183,7 @@ PMC * create_stable(PARROT_INTERP, REPROps *REPR, PMC *HOW) {
/* Performs a decontainerizing operation on the passed variable, using
* the 6model container API. */
PMC * decontainerize(PARROT_INTERP, PMC *var) {
if (var->vtable->base_type == smo_id) {
ContainerSpec *spec = STABLE(var)->container_spec;
if (spec && IS_CONCRETE(var)) {
if (!PMC_IS_NULL(spec->value_slot.class_handle)) {
/* Just get slot. */
return VTABLE_get_attr_keyed(interp, var, spec->value_slot.class_handle,
spec->value_slot.attr_name);
}
else {
/* Invoke FETCH method. */
PMC *old_ctx = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp));
PMC *meth = spec->fetch_method;
PMC *cappy = Parrot_pmc_new(interp, enum_class_CallContext);
VTABLE_push_pmc(interp, cappy, var);
Parrot_pcc_invoke_from_sig_object(interp, meth, cappy);
cappy = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp));
Parrot_pcc_set_signature(interp, CURRENT_CONTEXT(interp), old_ctx);
return VTABLE_get_pmc_keyed_int(interp, cappy, 0);
}
}
}
if (var->vtable->base_type == smo_id)
var = DECONT(interp, var);
return var;
}
42 changes: 36 additions & 6 deletions src/6model/sixmodelobject.h
Expand Up @@ -29,11 +29,32 @@ typedef struct {
INTVAL hint; /* Hint for use in static/gradual typing. */
} AttributeIdentifier;

/* Language interop information that we hold if the type is declaring a
* container of some sort. */
/* Container specification information, for types that serve as containers.
* A container is something that can be assigned into. It may be some kind
* of container object (like Perl 6's Scalar) or it may be a reference to a
* native lexical or object field. The function table determines the way it
* behaves. */
typedef struct {
AttributeIdentifier value_slot;
PMC *fetch_method;
/* Fetches a value out of a container. Used for decontainerization. */
PMC * (*fetch) (PARROT_INTERP, PMC *cont);

/* Stores a value in a container. Used for assignment. */
void (*store) (PARROT_INTERP, PMC *cont, PMC *obj);

/* Name of this container specification. */
STRING *name;

/* Marks container data, if any. */
void (*gc_mark_data) (PARROT_INTERP, STable *st);

/* Frees container data, if any. */
void (*gc_free_data) (PARROT_INTERP, STable *st);

/* Serializes the container data, if any. */
void (*serialize) (PARROT_INTERP, STable *st, SerializationWriter *writer);

/* Deserializes the container data, if any. */
void (*deserialize) (PARROT_INTERP, STable *st, SerializationReader *reader);
} ContainerSpec;

/* How do we invoke this thing? Specifies either an attribute to look at for
Expand Down Expand Up @@ -138,10 +159,14 @@ struct SixModel_STable {
INTVAL type_cache_id;

/* If this is a container, then this contains information needed in
* order to fetch the value in it. If not, it'll be null, which can
* be taken as a "not a container" indication. */
* order to fetch the value in it or assign a value to it. If not,
* it'll be null, which can be taken as a "not a container" indication. */
ContainerSpec *container_spec;

/* Data that the container spec may need to function. */
/* Any data specific to this type that the REPR wants to keep. */
void *container_data;

/* If this is invokable, then this contains information needed to
* figure out how to invoke it. If not, it'll be null. */
InvocationSpec *invocation_spec;
Expand Down Expand Up @@ -394,6 +419,11 @@ struct SixModel_REPROps {
#define IS_CONCRETE(o) (!PObj_flag_TEST(private0, (o)))
#define MARK_AS_TYPE_OBJECT(o) PObj_flag_SET(private0, (o))

/* Macro for decontainerization. */
#define DECONT(interp, o) (STABLE(o)->container_spec ? \
STABLE(o)->container_spec->fetch(interp, o) : \
o)

/* Write barriers for noticing changes to objects or STables with an SC. */
typedef void (* obj_sc_barrier_func) (PARROT_INTERP, PMC *obj);
typedef void (* st_sc_barrier_func) (PARROT_INTERP, STable *st);
Expand Down
23 changes: 2 additions & 21 deletions src/ops/nqp_dyncall.ops
Expand Up @@ -545,27 +545,8 @@ unmarshal_callback(PARROT_INTERP, PMC *value, PMC *info) {
}

PMC * decontainerize(PARROT_INTERP, PMC *var) {
if (var->vtable->base_type == smo_id) {
ContainerSpec *spec = STABLE(var)->container_spec;
if (spec && IS_CONCRETE(var)) {
if (!PMC_IS_NULL(spec->value_slot.class_handle)) {
/* Just get slot. */
return VTABLE_get_attr_keyed(interp, var, spec->value_slot.class_handle,
spec->value_slot.attr_name);
}
else {
/* Invoke FETCH method. */
PMC *old_ctx = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp));
PMC *meth = spec->fetch_method;
PMC *cappy = Parrot_pmc_new(interp, enum_class_CallContext);
VTABLE_push_pmc(interp, cappy, var);
Parrot_pcc_invoke_from_sig_object(interp, meth, cappy);
cappy = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp));
Parrot_pcc_set_signature(interp, CURRENT_CONTEXT(interp), old_ctx);
return VTABLE_get_pmc_keyed_int(interp, cappy, 0);
}
}
}
if (var->vtable->base_type == smo_id)
var = DECONT(interp, var);
return var;
}

Expand Down

0 comments on commit 11b1430

Please sign in to comment.