Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add container spec registry and code_pair spec.
The registry keeps track of different containerization strategies we
have. Implemented one that relies on a pair of code objects (a fetch
and a store), which provides one aspect of the previous functionality.
  • Loading branch information
jnthn committed Mar 19, 2013
1 parent 564d659 commit d5acd05
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 0 deletions.
140 changes: 140 additions & 0 deletions src/6model/containers.c
@@ -0,0 +1,140 @@
#define PARROT_IN_EXTENSION
#include "parrot/parrot.h"
#include "parrot/extend.h"
#include "sixmodelobject.h"

/* ***************************************************************************
* CodePair container configuration: container with FETCH/STORE code refs
* ***************************************************************************/

typedef struct {
PMC *fetch_code;
PMC *store_code;
} CodePairContData;

static PMC * code_pair_fetch(PARROT_INTERP, PMC *cont) {
CodePairContData *data = (CodePairContData *)STABLE(cont)->container_data;
PMC *old_ctx = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp));
PMC *cappy = Parrot_pmc_new(interp, enum_class_CallContext);
VTABLE_push_pmc(interp, cappy, cont);
Parrot_pcc_invoke_from_sig_object(interp, data->fetch_code, 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);
}

static void code_pair_store(PARROT_INTERP, PMC *cont, PMC *value) {
CodePairContData *data = (CodePairContData *)STABLE(cont)->container_data;
PMC *old_ctx = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp));
PMC *cappy = Parrot_pmc_new(interp, enum_class_CallContext);
VTABLE_push_pmc(interp, cappy, cont);
VTABLE_push_pmc(interp, cappy, value);
Parrot_pcc_invoke_from_sig_object(interp, data->store_code, cappy);
Parrot_pcc_set_signature(interp, CURRENT_CONTEXT(interp), old_ctx);
}

static void code_pair_gc_mark_data(PARROT_INTERP, STable *st) {
CodePairContData *data = (CodePairContData *)st->container_data;
Parrot_gc_mark_PMC_alive(interp, data->fetch_code);
Parrot_gc_mark_PMC_alive(interp, data->store_code);
}

static void code_pair_gc_mem_sys_free_data(PARROT_INTERP, STable *st) {
if (st->container_data) {
mem_sys_free(st->container_data);
st->container_data = NULL;
}
}

static void code_pair_serialize(PARROT_INTERP, STable *st, SerializationWriter *writer) {
CodePairContData *data = (CodePairContData *)st->container_data;
writer->write_ref(interp, writer, data->fetch_code);
writer->write_ref(interp, writer, data->store_code);
}

static void code_pair_deserialize(PARROT_INTERP, STable *st, SerializationReader *reader) {
CodePairContData *data = (CodePairContData *)st->container_data;
data->fetch_code = reader->read_ref(interp, reader);
data->store_code = reader->read_ref(interp, reader);
}

static ContainerSpec *code_pair_spec = NULL;

static void code_pair_set_container_spec(PARROT_INTERP, STable *st) {
CodePairContData *data = mem_sys_allocate(sizeof(CodePairContData));
data->fetch_code = PMCNULL;
data->store_code = PMCNULL;
st->container_data = data;
st->container_spec = code_pair_spec;
}

static void code_pair_configure_container_spec(PARROT_INTERP, STable *st, PMC *config) {
CodePairContData *data = (CodePairContData *)st->container_data;
STRING *fetch = Parrot_str_new_constant(interp, "fetch");
STRING *store = Parrot_str_new_constant(interp, "store");
if (!VTABLE_exists_keyed_str(interp, config, fetch))
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"Container spec 'code_pair' must be configured with a fetch");
if (!VTABLE_exists_keyed_str(interp, config, store))
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"Container spec 'code_pair' must be configured with a store");
data->fetch_code = VTABLE_get_pmc_keyed_str(interp, config, fetch);
data->store_code = VTABLE_get_pmc_keyed_str(interp, config, store);
}

static ContainerConfigurer * initialize_code_pair_spec(PARROT_INTERP) {
ContainerConfigurer *cc = mem_sys_allocate(sizeof(ContainerConfigurer));

code_pair_spec = mem_sys_allocate(sizeof(ContainerSpec));
code_pair_spec->name = Parrot_str_new_constant(interp, "code_pair");
code_pair_spec->fetch = code_pair_fetch;
code_pair_spec->store = code_pair_store;
code_pair_spec->gc_mark_data = code_pair_gc_mark_data;
code_pair_spec->gc_mem_sys_free_data = code_pair_gc_mem_sys_free_data;
code_pair_spec->serialize = code_pair_serialize;
code_pair_spec->deserialize = code_pair_deserialize;

cc->set_container_spec = code_pair_set_container_spec;
cc->configure_container_spec = code_pair_configure_container_spec;

return cc;
}

/* ***************************************************************************
* Container registry and configuration
* ***************************************************************************/

/* Container registry is a hash mapping names of container configurations
* to function tables. */
static PMC *container_registry = NULL;

/* Adds a container configurer to the registry. */
void SixModelObject_add_container_config(PARROT_INTERP, STRING *name,
ContainerConfigurer *configurer) {
PMC *wrapper = Parrot_pmc_new(interp, enum_class_Pointer);
VTABLE_set_pointer(interp, wrapper, configurer);
VTABLE_set_pmc_keyed_str(interp, container_registry, name, wrapper);
}

/* Gets a container configurer from the registry. */
ContainerConfigurer * SixModelObject_get_container_config(PARROT_INTERP, STRING *name) {
if (VTABLE_exists_keyed_str(interp, container_registry, name))
return (ContainerConfigurer *)VTABLE_get_pointer(interp,
VTABLE_get_pmc_keyed_str(interp, container_registry, name));
else
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"No such container spec '%Ss'", name);
}

/* Does initial setup work of the container registry, including registering
* the various built-in container types. */
void SixModelObject_containers_setup(PARROT_INTERP) {
/* Initialize registry. */
container_registry = Parrot_pmc_new(interp, enum_class_Hash);
Parrot_pmc_gc_register(interp, container_registry);

/* Add built-in configurations. */
SixModelObject_add_container_config(interp,
Parrot_str_new_constant(interp, "code_pair"),
initialize_code_pair_spec(interp));
}
4 changes: 4 additions & 0 deletions src/6model/containers.h
@@ -0,0 +1,4 @@
void SixModelObject_add_container_config(PARROT_INTERP, STRING *name,
ContainerConfigurer *configurer);
ContainerConfigurer * SixModelObject_get_container_config(PARROT_INTERP, STRING *name);
void SixModelObject_containers_setup(PARROT_INTERP);
10 changes: 10 additions & 0 deletions src/6model/sixmodelobject.h
Expand Up @@ -57,6 +57,16 @@ typedef struct {
void (*deserialize) (PARROT_INTERP, STable *st, SerializationReader *reader);
} ContainerSpec;

/* A container configurer knows how to attach a certain type of container
* to an STable and configure it. */
typedef struct {
/* Sets this container spec in place for the specified STable. */
void (*set_container_spec) (PARROT_INTERP, STable *st);

/* Configures the container spec with the specified info. */
void (*configure_container_spec) (PARROT_INTERP, STable *st, PMC *config);
} ContainerConfigurer;

/* How do we invoke this thing? Specifies either an attribute to look at for
* an invokable thing, or alternatively a method to call. */
typedef struct {
Expand Down
4 changes: 4 additions & 0 deletions src/ops/nqp.ops
Expand Up @@ -10,6 +10,7 @@ BEGIN_OPS_PREAMBLE
#include "../6model/repr_registry.h"
#include "../6model/reprs/NFA.h"
#include "../6model/serialization_context.h"
#include "../6model/containers.h"
#include "../guts/multi_dispatch.h"
#include "../pmc/pmc_nqplexinfo.h"
#include "pmc_sub.h"
Expand Down Expand Up @@ -322,6 +323,9 @@ inline op nqp_dynop_setup() :base_core {
/* Initialize the object model. */
SixModelObject_initialize(interp, &KnowHOW, &KnowHOWAttribute);

/* Initialize the container system. */
SixModelObject_containers_setup(interp);

/* Initialize compiling SCs list. */
compiling_scs = Parrot_pmc_new(interp, enum_class_ResizablePMCArray);
Parrot_pmc_gc_register(interp, compiling_scs);
Expand Down
3 changes: 3 additions & 0 deletions tools/build/Makefile.in
Expand Up @@ -224,6 +224,7 @@ METAMODEL_SOURCE = src/6model/sixmodelobject.h src/6model/sixmodelobject.c \
src/6model/serialization_context.h src/6model/serialization.c \
src/6model/serialization.h src/guts/multi_dispatch.h \
src/guts/multi_dispatch.c src/6model/base64.c src/6model/base64.h \
src/6model/containers.h src/6model/containers.c \

METAMODEL_OBJS = ../6model/sixmodelobject$(O) ../6model/repr_registry$(O) \
../6model/knowhow_bootstrapper$(O) ../6model/reprs/KnowHOWREPR$(O) \
Expand All @@ -234,6 +235,7 @@ METAMODEL_OBJS = ../6model/sixmodelobject$(O) ../6model/repr_registry$(O) \
../6model/reprs/VMHash$(O) ../6model/reprs/VMIter$(O) \
../6model/serialization_context$(O) ../6model/base64$(O) \
../6model/serialization$(O) ../guts/multi_dispatch$(O) \
../6model/containers$(O) \

LIBTOMMATH_BIN = $(TOM)core$(O) \
$(TOM)_error$(O) \
Expand Down Expand Up @@ -797,6 +799,7 @@ $(OPS_DIR)/$(OPS)$(LOAD_EXT): $(OPS_DIR)/$(OPS_SOURCE) $(DYNPMC)
cd src/6model && $(CC) -c @cc_o_out@serialization$(O) -I../../$(PMC_DIR) $(CINCLUDES) $(CFLAGS) serialization.c
cd src/6model && $(CC) -c @cc_o_out@base64$(O) -I../../$(PMC_DIR) $(CINCLUDES) $(CFLAGS) base64.c
cd src/guts && $(CC) -c @cc_o_out@multi_dispatch$(O) -I../../$(PMC_DIR) $(CINCLUDES) $(CFLAGS) multi_dispatch.c
cd src/6model && $(CC) -c @cc_o_out@containers$(O) -I../../$(PMC_DIR) $(CINCLUDES) $(CFLAGS) containers.c
cd 3rdparty/sha1 && $(CC) -c @cc_o_out@sha1$(O) $(CINCLUDES) $(CFLAGS) sha1.c
cd $(OPS_DIR) && $(LD) @ld_out@$(OPS)$(LOAD_EXT) $(OPS)$(O) $(METAMODEL_OBJS) ../../3rdparty/sha1/sha1$(O) $(LINKARGS)

Expand Down

0 comments on commit d5acd05

Please sign in to comment.