-
Notifications
You must be signed in to change notification settings - Fork 171
/
NativeCall.c
143 lines (124 loc) · 4.85 KB
/
NativeCall.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#include "moar.h"
/* This representation's function pointer table. */
static const MVMREPROps NativeCall_this_repr;
/* Creates a new type object of this representation, and associates it with
* the given HOW. Also sets the invocation protocol handler in the STable. */
static MVMObject * type_object_for(MVMThreadContext *tc, MVMObject *HOW) {
MVMSTable *st = MVM_gc_allocate_stable(tc, &NativeCall_this_repr, HOW);
MVMROOT(tc, st, {
MVMObject *obj = MVM_gc_allocate_type_object(tc, st);
MVM_ASSIGN_REF(tc, &(st->header), st->WHAT, obj);
st->size = sizeof(MVMNativeCall);
});
return st->WHAT;
}
/* Copies the body of one object to another. */
static void copy_to(MVMThreadContext *tc, MVMSTable *st, void *src, MVMObject *dest_root, void *dest) {
MVMNativeCallBody *src_body = (MVMNativeCallBody *)src;
MVMNativeCallBody *dest_body = (MVMNativeCallBody *)dest;
/* Need a fresh handle for resource management purposes. */
if (src_body->lib_name) {
dest_body->lib_name = MVM_malloc(strlen(src_body->lib_name) + 1);
strcpy(dest_body->lib_name, src_body->lib_name);
dest_body->lib_handle = MVM_nativecall_load_lib(dest_body->lib_name);
}
/* Rest is just simple copying. */
dest_body->entry_point = src_body->entry_point;
dest_body->convention = src_body->convention;
dest_body->num_args = src_body->num_args;
if (src_body->arg_types) {
dest_body->arg_types = MVM_malloc(sizeof(MVMint16) * (src_body->num_args ? src_body->num_args : 1));
memcpy(dest_body->arg_types, src_body->arg_types, src_body->num_args * sizeof(MVMint16));
}
dest_body->ret_type = src_body->ret_type;
if (src_body->jitcode) {
dest_body->jitcode = MVM_jit_code_copy(tc, src_body->jitcode);
}
else
dest_body->jitcode = NULL;
}
static const MVMStorageSpec storage_spec = {
MVM_STORAGE_SPEC_INLINED, /* inlineable */
sizeof(MVMNativeCallBody) * 8, /* bits */
ALIGNOF(MVMNativeCallBody), /* align */
MVM_STORAGE_SPEC_BP_NONE, /* boxed_primitive */
0, /* can_box */
0, /* is_unsigned */
};
/* Gets the storage specification for this representation. */
static const MVMStorageSpec * get_storage_spec(MVMThreadContext *tc, MVMSTable *st) {
return &storage_spec;
}
/* We can't actually serialize the handle, but since this REPR gets inlined
* we just do nothing here since it may well have never been opened. Various
* more involved approaches are possible. */
static void serialize(MVMThreadContext *tc, MVMSTable *st, void *data, MVMSerializationWriter *writer) {
}
static void deserialize_stable_size(MVMThreadContext *tc, MVMSTable *st, MVMSerializationReader *reader) {
st->size = sizeof(MVMNativeCall);
}
static void deserialize(MVMThreadContext *tc, MVMSTable *st, MVMObject *root, void *data, MVMSerializationReader *reader) {
}
static void gc_mark(MVMThreadContext *tc, MVMSTable *st, void *data, MVMGCWorklist *worklist) {
MVMNativeCallBody *body = (MVMNativeCallBody *)data;
if (body->arg_info) {
MVMint16 i;
for (i = 0; i < body->num_args; i++)
if (body->arg_info[i])
MVM_gc_worklist_add(tc, worklist, &body->arg_info[i]);
}
}
static void gc_cleanup(MVMThreadContext *tc, MVMSTable *st, void *data) {
MVMNativeCallBody *body = (MVMNativeCallBody *)data;
if (body->lib_name)
MVM_free(body->lib_name);
if (body->lib_handle)
MVM_nativecall_free_lib(body->lib_handle);
if (body->arg_types)
MVM_free(body->arg_types);
if (body->arg_info)
MVM_free(body->arg_info);
if (body->jitcode)
MVM_jit_code_destroy(tc, body->jitcode);
}
static void gc_free(MVMThreadContext *tc, MVMObject *obj) {
gc_cleanup(tc, STABLE(obj), OBJECT_BODY(obj));
}
/* Compose the representation. */
static void compose(MVMThreadContext *tc, MVMSTable *st, MVMObject *info) {
/* Nothing to do for this REPR. */
}
/* Initializes the representation. */
const MVMREPROps * MVMNativeCall_initialize(MVMThreadContext *tc) {
return &NativeCall_this_repr;
}
static const MVMREPROps NativeCall_this_repr = {
type_object_for,
MVM_gc_allocate_object,
NULL, /* initialize */
copy_to,
MVM_REPR_DEFAULT_ATTR_FUNCS,
MVM_REPR_DEFAULT_BOX_FUNCS,
MVM_REPR_DEFAULT_POS_FUNCS,
MVM_REPR_DEFAULT_ASS_FUNCS,
MVM_REPR_DEFAULT_ELEMS,
get_storage_spec,
NULL, /* change_type */
serialize,
deserialize,
NULL, /* serialize_repr_data */
NULL, /* deserialize_repr_data */
deserialize_stable_size,
gc_mark,
gc_free,
gc_cleanup,
NULL, /* gc_mark_repr_data */
NULL, /* gc_free_repr_data */
compose,
NULL, /* spesh */
NULL, /* jit */
"NativeCall", /* name */
MVM_REPR_ID_MVMNativeCall,
NULL, /* unmanaged_size */
NULL, /* describe_refs */
};