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