Skip to content

Commit 837fa8b

Browse files
committed
Add a NativeCall REPR and get it filled out enough for now; may need a re-visit later for callback support.
1 parent 0166457 commit 837fa8b

File tree

3 files changed

+238
-1
lines changed

3 files changed

+238
-1
lines changed

src/6model/reprs/NativeCall.c

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
#define PARROT_IN_EXTENSION
2+
#include "parrot/parrot.h"
3+
#include "parrot/extend.h"
4+
#include "../sixmodelobject.h"
5+
#include "NativeCall.h"
6+
7+
/* This representation's function pointer table. */
8+
static REPROps *this_repr;
9+
10+
/* Some functions we have to get references to. */
11+
static PMC * (* wrap_object_func) (PARROT_INTERP, void *obj);
12+
static PMC * (* create_stable_func) (PARROT_INTERP, REPROps *REPR, PMC *HOW);
13+
14+
/* Creates a new type object of this representation, and associates it with
15+
* the given HOW. */
16+
static PMC * type_object_for(PARROT_INTERP, PMC *HOW) {
17+
/* Create new object instance. */
18+
NativeCallInstance *obj = mem_allocate_zeroed_typed(NativeCallInstance);
19+
20+
/* Build an STable. */
21+
PMC *st_pmc = create_stable_func(interp, this_repr, HOW);
22+
STable *st = STABLE_STRUCT(st_pmc);
23+
24+
/* Create type object and point it back at the STable. */
25+
obj->common.stable = st_pmc;
26+
st->WHAT = wrap_object_func(interp, obj);
27+
PARROT_GC_WRITE_BARRIER(interp, st_pmc);
28+
29+
/* Flag it as a type object. */
30+
MARK_AS_TYPE_OBJECT(st->WHAT);
31+
32+
return st->WHAT;
33+
}
34+
35+
/* Creates a new instance based on the type object. */
36+
static PMC * allocate(PARROT_INTERP, STable *st) {
37+
NativeCallInstance *obj = mem_allocate_zeroed_typed(NativeCallInstance);
38+
obj->common.stable = st->stable_pmc;
39+
return wrap_object_func(interp, obj);
40+
}
41+
42+
/* Initialize a new instance. */
43+
static void initialize(PARROT_INTERP, STable *st, void *data) {
44+
/* Nothing to do here. */
45+
}
46+
47+
/* Copies to the body of one object to another. */
48+
static void copy_to(PARROT_INTERP, STable *st, void *src, void *dest) {
49+
NativeCallBody *src_body = (NativeCallBody *)src;
50+
NativeCallBody *dest_body = (NativeCallBody *)dest;
51+
52+
/* Need a fresh handle for resource management purposes. */
53+
dest_body->lib_name = mem_sys_allocate(strlen(dest_body->lib_name) + 1);
54+
strcpy(dest_body->lib_name, src_body->lib_name);
55+
dest_body->lib_handle = dlLoadLibrary(dest_body->lib_name);
56+
57+
/* Rest is just simple copying. */
58+
dest_body->entry_point = src_body->entry_point;
59+
dest_body->num_args = src_body->num_args;
60+
dest_body->arg_types = mem_sys_allocate(src_body->num_args * sizeof(INTVAL));
61+
memcpy(dest_body->arg_types, src_body->arg_types, src_body->num_args * sizeof(INTVAL));
62+
dest_body->ret_type = src_body->ret_type;
63+
}
64+
65+
/* Helper to die because this type doesn't support attributes. */
66+
PARROT_DOES_NOT_RETURN
67+
static void die_no_attrs(PARROT_INTERP) {
68+
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
69+
"NativeCall representation does not support attribute storage");
70+
}
71+
72+
/* Gets the current value for an attribute. */
73+
static PMC * get_attribute_boxed(PARROT_INTERP, STable *st, void *data, PMC *class_handle, STRING *name, INTVAL hint) {
74+
die_no_attrs(interp);
75+
}
76+
static void * get_attribute_ref(PARROT_INTERP, STable *st, void *data, PMC *class_handle, STRING *name, INTVAL hint) {
77+
die_no_attrs(interp);
78+
}
79+
80+
/* Binds the given value to the specified attribute. */
81+
static void bind_attribute_boxed(PARROT_INTERP, STable *st, void *data, PMC *class_handle, STRING *name, INTVAL hint, PMC *value) {
82+
die_no_attrs(interp);
83+
}
84+
static void bind_attribute_ref(PARROT_INTERP, STable *st, void *data, PMC *class_handle, STRING *name, INTVAL hint, void *value) {
85+
die_no_attrs(interp);
86+
}
87+
88+
/* Gets the hint for the given attribute ID. */
89+
static INTVAL hint_for(PARROT_INTERP, STable *st, PMC *class_handle, STRING *name) {
90+
return NO_HINT;
91+
}
92+
93+
/* Used with boxing. Sets an integer value, for representations that can hold
94+
* one. */
95+
static void set_int(PARROT_INTERP, STable *st, void *data, INTVAL value) {
96+
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
97+
"NativeCall cannot box a native int");
98+
}
99+
100+
/* Used with boxing. Gets an integer value, for representations that can
101+
* hold one. */
102+
static INTVAL get_int(PARROT_INTERP, STable *st, void *data) {
103+
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
104+
"NativeCall cannot unbox to a native int");
105+
}
106+
107+
/* Used with boxing. Sets a floating point value, for representations that can
108+
* hold one. */
109+
static void set_num(PARROT_INTERP, STable *st, void *data, FLOATVAL value) {
110+
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
111+
"NativeCall cannot box a native num");
112+
}
113+
114+
/* Used with boxing. Gets a floating point value, for representations that can
115+
* hold one. */
116+
static FLOATVAL get_num(PARROT_INTERP, STable *st, void *data) {
117+
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
118+
"NativeCall cannot unbox to a native num");
119+
}
120+
121+
/* Used with boxing. Sets a string value, for representations that can hold
122+
* one. */
123+
static void set_str(PARROT_INTERP, STable *st, void *data, STRING *value) {
124+
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
125+
"NativeCall cannot box a native string");
126+
}
127+
128+
/* Used with boxing. Gets a string value, for representations that can hold
129+
* one. */
130+
static STRING * get_str(PARROT_INTERP, STable *st, void *data) {
131+
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
132+
"NativeCall cannot unbox to a native string");
133+
}
134+
135+
/* Some objects serve primarily as boxes of others, inlining them. This gets
136+
* gets the reference to such things, using the representation ID to distinguish
137+
* them. */
138+
static void * get_boxed_ref(PARROT_INTERP, STable *st, void *data, INTVAL repr_id) {
139+
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
140+
"NativeCall cannot box other types");
141+
}
142+
143+
/* This is called to do any cleanup of resources when an object gets
144+
* embedded inside another one. Never called on a top-level object. */
145+
static void gc_cleanup(PARROT_INTERP, STable *st, void *data) {
146+
NativeCallBody *body = (NativeCallBody *)data;
147+
if (body->lib_handle)
148+
dlFreeLibrary(body->lib_handle);
149+
if (body->arg_types)
150+
mem_sys_free(body->arg_types);
151+
}
152+
153+
/* This Parrot-specific addition to the API is used to free an object. */
154+
static void gc_free(PARROT_INTERP, PMC *obj) {
155+
gc_cleanup(interp, STABLE(obj), OBJECT_BODY(obj));
156+
mem_sys_free(PMC_data(obj));
157+
PMC_data(obj) = NULL;
158+
}
159+
160+
/* Gets the storage specification for this representation. */
161+
static storage_spec get_storage_spec(PARROT_INTERP, STable *st) {
162+
storage_spec spec;
163+
spec.inlineable = STORAGE_SPEC_INLINED;
164+
spec.bits = sizeof(NativeCallBody) * 8;
165+
spec.boxed_primitive = STORAGE_SPEC_BP_NONE;
166+
return spec;
167+
}
168+
169+
/* Checks if an attribute has been initialized. */
170+
static INTVAL is_attribute_initialized(PARROT_INTERP, STable *st, void *data, PMC *ClassHandle, STRING *Name, INTVAL Hint) {
171+
die_no_attrs(interp);
172+
}
173+
174+
/* Initializes the NativeCall representation. */
175+
REPROps * NativeCall_initialize(PARROT_INTERP,
176+
PMC * (* wrap_object_func_ptr) (PARROT_INTERP, void *obj),
177+
PMC * (* create_stable_func_ptr) (PARROT_INTERP, REPROps *REPR, PMC *HOW)) {
178+
/* Stash away functions passed wrapping functions. */
179+
wrap_object_func = wrap_object_func_ptr;
180+
create_stable_func = create_stable_func_ptr;
181+
182+
/* Allocate and populate the representation function table. */
183+
this_repr = mem_allocate_typed(REPROps);
184+
this_repr->type_object_for = type_object_for;
185+
this_repr->allocate = allocate;
186+
this_repr->initialize = initialize;
187+
this_repr->copy_to = copy_to;
188+
this_repr->get_attribute_boxed = get_attribute_boxed;
189+
this_repr->get_attribute_boxed = get_attribute_boxed;
190+
this_repr->bind_attribute_boxed = bind_attribute_boxed;
191+
this_repr->bind_attribute_ref = bind_attribute_ref;
192+
this_repr->hint_for = hint_for;
193+
this_repr->set_int = set_int;
194+
this_repr->get_int = get_int;
195+
this_repr->set_num = set_num;
196+
this_repr->get_num = get_num;
197+
this_repr->set_str = set_str;
198+
this_repr->get_str = get_str;
199+
this_repr->get_boxed_ref = get_boxed_ref;
200+
this_repr->gc_mark = NULL;
201+
this_repr->gc_free = gc_free;
202+
this_repr->gc_cleanup = gc_cleanup;
203+
this_repr->gc_mark_repr_data = NULL;
204+
this_repr->gc_free_repr_data = NULL;
205+
this_repr->get_storage_spec = get_storage_spec;
206+
this_repr->is_attribute_initialized = is_attribute_initialized;
207+
return this_repr;
208+
}

src/6model/reprs/NativeCall.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#ifndef NATIVECALL_H_GUARD
2+
#define NATIVECALL_H_GUARD
3+
4+
#include "dyncall/dyncall.h"
5+
#include "dynload/dynload.h"
6+
7+
/* Body of a NativeCall. */
8+
typedef struct {
9+
char *lib_name;
10+
void *lib_handle;
11+
void *entry_point;
12+
INTVAL num_args;
13+
INTVAL *arg_types;
14+
INTVAL ret_type;
15+
} NativeCallBody;
16+
17+
/* This is how an instance with the NativeCall representation looks. */
18+
typedef struct {
19+
SixModelObjectCommonalities common;
20+
NativeCallBody body;
21+
} NativeCallInstance;
22+
23+
/* Initializes the NativeCall REPR. */
24+
REPROps * NativeCall_initialize(PARROT_INTERP,
25+
PMC * (* wrap_object_func_ptr) (PARROT_INTERP, void *obj),
26+
PMC * (* create_stable_func_ptr) (PARROT_INTERP, REPROps *REPR, PMC *HOW));
27+
28+
#endif

tools/build/Makefile.in

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -954,7 +954,8 @@ $(DYNCALL_BIN):
954954
$(OPS_DIR)/$(DYNCALL_OPS)$(LOAD_EXT): $(OPS_DIR)/$(DYNCALL_OPS_SOURCE) $(DYNCALL_BIN)
955955
cd $(OPS_DIR) && $(OPS2C) C --dynamic $(DYNCALL_OPS_SOURCE)
956956
cd $(OPS_DIR) && $(CC) -c @cc_o_out@$(DYNCALL_OPS)$(O) $(CINCLUDES) -I../../3rdparty/dyncall-0.6 $(CFLAGS) $(DYNCALL_OPS).c
957-
cd $(OPS_DIR) && $(LD) @ld_out@$(DYNCALL_OPS)$(LOAD_EXT) $(DYNCALL_OPS)$(O) ../../3rdparty/dyncall-0.6/dyncall/libdyncall_s$(A) ../../3rdparty/dyncall-0.6/dyncallback/libdyncallback_s$(A) ../../3rdparty/dyncall-0.6/dynload/libdynload_s$(A) $(LINKARGS)
957+
cd src/6model/reprs && $(CC) -c @cc_o_out@NativeCall$(O) -I../../../$(PMC_DIR) -I../../../3rdparty/dyncall-0.6 $(CINCLUDES) $(CFLAGS) NativeCall.c
958+
cd $(OPS_DIR) && $(LD) @ld_out@$(DYNCALL_OPS)$(LOAD_EXT) $(DYNCALL_OPS)$(O) ../6model/reprs/NativeCall$(O) ../../3rdparty/dyncall-0.6/dyncall/libdyncall_s$(A) ../../3rdparty/dyncall-0.6/dyncallback/libdyncallback_s$(A) ../../3rdparty/dyncall-0.6/dynload/libdynload_s$(A) $(LINKARGS)
958959

959960
bootstrap-files: $(STAGE2_PBCS) src/stage2/$(CORE_SETTING_NQP)
960961
$(PERL) tools/build/gen-bootstrap.pl src/Regex.pir >src/stage0/Regex-s0.pir

0 commit comments

Comments
 (0)