/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 | dest_body->jitcode = src_body->jitcode; |
42 | 0 | } |
43 | | |
44 | | |
45 | | |
46 | | static const MVMStorageSpec storage_spec = { |
47 | | MVM_STORAGE_SPEC_INLINED, /* inlineable */ |
48 | | sizeof(MVMNativeCallBody) * 8, /* bits */ |
49 | | ALIGNOF(MVMNativeCallBody), /* align */ |
50 | | MVM_STORAGE_SPEC_BP_NONE, /* boxed_primitive */ |
51 | | 0, /* can_box */ |
52 | | 0, /* is_unsigned */ |
53 | | }; |
54 | | |
55 | | |
56 | | /* Gets the storage specification for this representation. */ |
57 | 0 | static const MVMStorageSpec * get_storage_spec(MVMThreadContext *tc, MVMSTable *st) { |
58 | 0 | return &storage_spec; |
59 | 0 | } |
60 | | |
61 | | /* We can't actually serialize the handle, but since this REPR gets inlined |
62 | | * we just do nothing here since it may well have never been opened. Various |
63 | | * more involved approaches are possible. */ |
64 | 0 | static void serialize(MVMThreadContext *tc, MVMSTable *st, void *data, MVMSerializationWriter *writer) { |
65 | 0 | } |
66 | 0 | static void deserialize_stable_size(MVMThreadContext *tc, MVMSTable *st, MVMSerializationReader *reader) { |
67 | 0 | st->size = sizeof(MVMNativeCall); |
68 | 0 | } |
69 | 0 | static void deserialize(MVMThreadContext *tc, MVMSTable *st, MVMObject *root, void *data, MVMSerializationReader *reader) { |
70 | 0 | } |
71 | | |
72 | 0 | static void gc_mark(MVMThreadContext *tc, MVMSTable *st, void *data, MVMGCWorklist *worklist) { |
73 | 0 | MVMNativeCallBody *body = (MVMNativeCallBody *)data; |
74 | 0 | if (body->arg_info) { |
75 | 0 | MVMint16 i; |
76 | 0 | for (i = 0; i < body->num_args; i++) |
77 | 0 | if (body->arg_info[i]) |
78 | 0 | MVM_gc_worklist_add(tc, worklist, &body->arg_info[i]); |
79 | 0 | } |
80 | 0 | } |
81 | | |
82 | 0 | static void gc_cleanup(MVMThreadContext *tc, MVMSTable *st, void *data) { |
83 | 0 | MVMNativeCallBody *body = (MVMNativeCallBody *)data; |
84 | 0 | if (body->lib_name) |
85 | 0 | MVM_free(body->lib_name); |
86 | 0 | if (body->lib_handle) |
87 | 0 | MVM_nativecall_free_lib(body->lib_handle); |
88 | 0 | if (body->arg_types) |
89 | 0 | MVM_free(body->arg_types); |
90 | 0 | if (body->arg_info) |
91 | 0 | MVM_free(body->arg_info); |
92 | 0 | if (body->jitcode) |
93 | 0 | MVM_jit_code_destroy(tc, body->jitcode); |
94 | 0 | } |
95 | | |
96 | 0 | static void gc_free(MVMThreadContext *tc, MVMObject *obj) { |
97 | 0 | gc_cleanup(tc, STABLE(obj), OBJECT_BODY(obj)); |
98 | 0 | } |
99 | | |
100 | | /* Compose the representation. */ |
101 | 1 | static void compose(MVMThreadContext *tc, MVMSTable *st, MVMObject *info) { |
102 | 1 | /* Nothing to do for this REPR. */ |
103 | 1 | } |
104 | | |
105 | | /* Initializes the representation. */ |
106 | 144 | const MVMREPROps * MVMNativeCall_initialize(MVMThreadContext *tc) { |
107 | 144 | return &NativeCall_this_repr; |
108 | 144 | } |
109 | | |
110 | | static const MVMREPROps NativeCall_this_repr = { |
111 | | type_object_for, |
112 | | MVM_gc_allocate_object, |
113 | | NULL, /* initialize */ |
114 | | copy_to, |
115 | | MVM_REPR_DEFAULT_ATTR_FUNCS, |
116 | | MVM_REPR_DEFAULT_BOX_FUNCS, |
117 | | MVM_REPR_DEFAULT_POS_FUNCS, |
118 | | MVM_REPR_DEFAULT_ASS_FUNCS, |
119 | | MVM_REPR_DEFAULT_ELEMS, |
120 | | get_storage_spec, |
121 | | NULL, /* change_type */ |
122 | | serialize, |
123 | | deserialize, |
124 | | NULL, /* serialize_repr_data */ |
125 | | NULL, /* deserialize_repr_data */ |
126 | | deserialize_stable_size, |
127 | | gc_mark, |
128 | | gc_free, |
129 | | gc_cleanup, |
130 | | NULL, /* gc_mark_repr_data */ |
131 | | NULL, /* gc_free_repr_data */ |
132 | | compose, |
133 | | NULL, /* spesh */ |
134 | | "NativeCall", /* name */ |
135 | | MVM_REPR_ID_MVMNativeCall, |
136 | | NULL, /* unmanaged_size */ |
137 | | NULL, /* describe_refs */ |
138 | | }; |