comparison runtime/object.c @ 7:d61550e2c001

Added current work on new runtime
author Mike Pavone <pavone@retrodev.com>
date Wed, 13 May 2009 00:47:40 -0400
parents
children 31f8182f3433
comparison
equal deleted inserted replaced
6:f67d9be38ddf 7:d61550e2c001
1 #include "object.h"
2 #include "builtin.h"
3 #include <stdlib.h>
4 #include <string.h>
5 #include <stdio.h>
6
7 blueprint ** registered_types = NULL;
8 uint32_t max_registered_type = 0;
9 uint32_t type_storage = 0;
10
11 returntype call_method(uint32_t methodid, calldata * params)
12 {
13 int i;
14 blueprint * bp = get_blueprint(params->params[0]);
15 if(methodid >= bp->first_methodid && methodid < bp->last_methodid && bp->method_lookup[methodid - bp->first_methodid])
16 {
17 params->tail_func = bp->method_lookup[methodid - bp->first_methodid];
18 return TAIL_RETURN;
19 } else {
20 if(METHOD_MISSING >= bp->first_methodid && METHOD_MISSING < bp->last_methodid && bp->method_lookup[METHOD_MISSING - bp->first_methodid])
21 {
22 params->tail_func = bp->method_lookup[METHOD_MISSING - bp->first_methodid];
23 return TAIL_RETURN;
24 } else {
25 //TODO: Add useful info to exception
26 for(i = 0; i < params->num_params; ++i)
27 release_ref(params->params[i]);
28 params->params[0] = new_object(TYPE_METHODMISSINGEXCEPTION);
29 return EXCEPTION_RETURN;
30 }
31 }
32 }
33
34 returntype set_field(uint32_t setfieldid, calldata * params)
35 {
36 int i;
37 blueprint * bp = get_blueprint(params->params[0]);
38 if(setfieldid >= bp->first_setfieldid && setfieldid < bp->last_setfieldid && bp->setter_lookup[setfieldid - bp->first_setfieldid])
39 {
40 params->tail_func = bp->setter_lookup[setfieldid - bp->first_setfieldid];
41 return TAIL_RETURN;
42 } else {
43 if(METHOD_SETFIELDMISSING >= bp->first_setfieldid && METHOD_SETFIELDMISSING < bp->last_setfieldid && bp->method_lookup[METHOD_SETFIELDMISSING - bp->first_methodid])
44 {
45 params->tail_func = bp->method_lookup[METHOD_SETFIELDMISSING - bp->first_methodid];
46 params->original_methodid = setfieldid;
47 return TAIL_RETURN;
48 } else {
49 //TODO: Add useful info to exception
50 for(i = 0; i < params->num_params; ++i)
51 release_ref(params->params[i]);
52 params->params[0] = new_object(TYPE_FIELDMISSINGEXCEPTION);
53 return EXCEPTION_RETURN;
54 }
55 }
56 }
57
58
59 returntype get_field(uint32_t getfieldid, calldata * params)
60 {
61 int i;
62 blueprint * bp = get_blueprint(params->params[0]);
63 if(getfieldid >= bp->first_getfieldid && getfieldid < bp->last_getfieldid && bp->getter_lookup[getfieldid - bp->first_getfieldid])
64 {
65 params->tail_func = bp->getter_lookup[getfieldid - bp->first_getfieldid];
66 return TAIL_RETURN;
67 } else {
68 if(METHOD_GETFIELDMISSING >= bp->first_getfieldid && METHOD_GETFIELDMISSING < bp->last_getfieldid && bp->method_lookup[METHOD_GETFIELDMISSING - bp->first_methodid])
69 {
70 params->tail_func = bp->method_lookup[METHOD_GETFIELDMISSING - bp->first_methodid];
71 params->original_methodid = getfieldid;
72 return TAIL_RETURN;
73 } else {
74 //TODO: Add useful info to exception
75 for(i = 0; i < params->num_params; ++i)
76 release_ref(params->params[i]);
77 params->params[0] = new_object(TYPE_FIELDMISSINGEXCEPTION);
78 return EXCEPTION_RETURN;
79 }
80 }
81 }
82
83 returntype convert_to(uint32_t convertto, calldata * params)
84 {
85 int i;
86 blueprint * bp = get_blueprint(params->params[0]);
87 if(convertto >= bp->first_convertto && convertto < bp->last_convertto && bp->convert_to[convertto])
88 {
89 params->tail_func = bp->convert_to[convertto - bp->first_convertto];
90 return TAIL_RETURN;
91 } else {
92 return NO_CONVERSION;
93 }
94 }
95
96 returntype convert_from(uint32_t convertfrom, calldata * params)
97 {
98 int i;
99 blueprint * bp = registered_types[convertfrom];
100 if(convertfrom >= bp->first_convertfrom && convertfrom < bp->last_convertfrom && bp->convert_from[convertfrom])
101 {
102 params->tail_func = bp->convert_from[convertfrom - bp->first_convertfrom];
103 return TAIL_RETURN;
104 } else {
105 return NO_CONVERSION;
106 }
107 }
108
109 returntype coerce_value(uint32_t type, calldata * params)
110 {
111 int i;
112 blueprint * bp = get_blueprint(params->params[0]);
113 if(bp == registered_types[type])
114 return NORMAL_RETURN;
115 if(convert_to(type, params) == TAIL_RETURN)
116 return TAIL_RETURN;
117 if(convert_from(type, params) == TAIL_RETURN)
118 return TAIL_RETURN;
119 //TODO: Add useful info to exception
120 for(i = 0; i < params->num_params; ++i)
121 release_ref(params->params[i]);
122 params->params[0] = new_object(TYPE_WRONGTYPEEXCEPTION);
123 return EXCEPTION_RETURN;
124 }
125
126 object * alloc_object(blueprint * bp)
127 {
128 //TODO: Replace with something more performant
129 return malloc(bp->boxed_size);
130 }
131
132 void * alloc_variable(uint32_t size)
133 {
134 return malloc(size);
135 }
136
137 void dealloc_object(blueprint * bp, object * obj)
138 {
139 //TODO: Replace with something more performant
140 free(obj);
141 }
142
143 object * new_object(uint32_t type)
144 {
145 blueprint * bp;
146 object * ret;
147 if(type >= max_registered_type || !registered_types[type])
148 return NULL;
149 bp = registered_types[type];
150 ret = alloc_object(bp);
151 if(ret)
152 {
153 ret->bprint = bp;
154 rh_atomic_set(ret, refcount, 1);
155 memset(((char *)ret) + sizeof(object), '\0', bp->size);
156 bp->init(ret);
157 }
158 return ret;
159 }
160
161 multisize * new_multisize(uint32_t type, uint32_t size)
162 {
163 blueprint *bp;
164 multisize * ret;
165 if(type >= max_registered_type || !registered_types[type])
166 return NULL;
167 ret = alloc_variable(sizeof(multisize) + type);
168 if(ret)
169 {
170 bp = registered_types[type];
171 ret->base.bprint = bp;
172 ret->size = size;
173 rh_atomic_set(&(ret->base), refcount, 1);
174 memset(((char *)ret) + sizeof(multisize), '\0', size);
175 bp->init((object *)ret);
176 }
177 return ret;
178 }
179
180 object * copy_object(object * tocopy)
181 {
182 object * copy;
183 multisize * mcopy, *mtocopy;
184 blueprint * bp;
185 if(rh_atomic_get(tocopy, refcount) == 1)
186 return tocopy;
187 bp = get_blueprint(tocopy);
188 if(bp->size < 0) {
189 mtocopy = (multisize *)tocopy;
190 mcopy = alloc_variable(sizeof(multisize) + mtocopy->size);
191 mcopy->size = mtocopy->size;
192 memcpy(((char *)mcopy)+sizeof(multisize), ((char *)mtocopy)+sizeof(multisize), mtocopy->size);
193 copy = (object *)mcopy;
194 } else {
195 copy = alloc_object(bp);
196 memcpy(((char *)copy) + sizeof(object), ((char *)tocopy)+sizeof(object), bp->size);
197 }
198 copy->bprint = bp;
199 rh_atomic_set(copy, refcount, 1);
200 bp->copy(copy);
201 release_ref(tocopy);
202 return copy;
203 }
204
205 void free_object(object * obj)
206 {
207 blueprint * bp = get_blueprint(obj);
208 if(bp->cleanup)
209 bp->cleanup(obj);
210 dealloc_object(bp, obj);
211 }
212
213 void release_ref(object * obj)
214 {
215 if(rh_atomic_sub_testzero(obj, refcount, 1))
216 free_object(obj);
217 }
218
219 void check_type_storage(type)
220 {
221 uint32_t type_storage_temp;
222 blueprint ** temp;
223 if(type >= type_storage)
224 if(type_storage)
225 {
226 type_storage_temp = (type + (type_storage >> 1));
227 temp = realloc(registered_types, type_storage_temp * sizeof(blueprint *));
228 if(temp)
229 {
230 registered_types = temp;
231 memset(registered_types + type_storage, '\0', (type_storage_temp - type_storage) * sizeof(blueprint *));
232 type_storage = type_storage_temp;
233 }
234 else
235 {
236 free(registered_types);
237 fprintf(stderr, "Couldn't allocate %d bytes for type storage array\n", type_storage_temp * sizeof(blueprint *));
238 exit(-1);
239 }
240 } else {
241
242 if(type < INITIAL_TYPE_STORAGE)
243 type_storage =INITIAL_TYPE_STORAGE;
244 else
245 type_storage = type + 8;
246 registered_types = malloc(type_storage * sizeof(blueprint *));
247 if(registered_types)
248 memset(registered_types, '\0', type_storage * sizeof(blueprint *));
249 else
250 {
251 fprintf(stderr, "Couldn't allocate %d bytes for type storage array\n", type_storage * sizeof(blueprint *));
252 exit(-1);
253 }
254
255 }
256 }
257
258 void default_action(object * obj)
259 {
260 }
261
262 blueprint * new_blueprint(uint32_t type, uint32_t size, special_func init, special_func copy, special_func cleanup)
263 {
264 blueprint * bp = malloc(sizeof(blueprint));
265 if(bp)
266 {
267 bp->size = size;
268 bp->boxed_size = size >= 0 ? size + sizeof(object) : size;
269 bp->method_lookup = bp->getter_lookup = bp->setter_lookup = bp->convert_to = bp->convert_from = NULL;
270 bp->init = init ? init : default_action;
271 bp->copy = copy ? copy : default_action;
272 bp->cleanup = cleanup ? cleanup : default_action;
273 bp->first_methodid = bp->last_methodid = bp->first_getfieldid = bp->last_getfieldid = bp->first_setfieldid = bp->last_setfieldid = bp->first_convertto = bp->last_convertto = bp->first_convertfrom = bp->last_convertfrom = 0;
274 //TODO: Handle names
275 bp->name = NULL;
276 }
277 return bp;
278 }
279
280 blueprint * register_type_byid(uint32_t type, uint32_t size, special_func init, special_func copy, special_func cleanup)
281 {
282 check_type_storage(type);
283 if(registered_types[type])
284 return registered_types[type];
285 registered_types[type] = new_blueprint(type, size, init, copy, cleanup);
286 if(!registered_types[type])
287 {
288 fputs("Couldn't allocate new object blueprint\n", stderr);
289 exit(-1);
290 }
291 if(type >= max_registered_type)
292 max_registered_type = type + 1;
293 return registered_types[type];
294 }
295
296 void add_method(blueprint * bp, uint32_t methodid, rhope_func impl)
297 {
298 rhope_func * temp;
299 if(methodid < 1) {
300 fputs("Attempt to add a method with an ID < 1\n", stderr);
301 exit(-1);
302 }
303 if (!bp->method_lookup)
304 {
305 bp->method_lookup = malloc(sizeof(rhope_func) * INITIAL_METHOD_LOOKUP);
306 if(!bp->method_lookup) {
307 fprintf(stderr, "Couldn't allocate %d bytes for method lookup table\n", sizeof(rhope_func) * INITIAL_METHOD_LOOKUP);
308 exit(-1);
309 }
310 if(methodid - BELOW_INITIAL_METHOD < 1) {
311 bp->first_methodid = 1;
312 bp->last_methodid = 1+INITIAL_METHOD_LOOKUP;
313 } else {
314 bp->first_methodid = methodid - BELOW_INITIAL_METHOD;
315 bp->last_methodid = bp->first_methodid + INITIAL_METHOD_LOOKUP;
316 }
317 memset(bp->method_lookup, '\0', sizeof(rhope_func) * INITIAL_METHOD_LOOKUP);
318 } else {
319 if (methodid < bp->first_methodid) {
320 temp = bp->method_lookup;
321 //Note: if this gets changed to generating an exception on failure, we need to restore the original buffer
322 bp->method_lookup = malloc(sizeof(rhope_func) * (bp->last_methodid-methodid));
323 if(!bp->method_lookup) {
324 fprintf(stderr, "Couldn't allocate %d bytes for method lookup table\n", sizeof(rhope_func) * (bp->last_methodid-methodid));
325 exit(-1);
326 }
327 memset(bp->method_lookup, '\0', (bp->first_methodid-methodid) * sizeof(rhope_func));
328 memcpy(bp->method_lookup + bp->first_methodid-methodid, temp, (bp->last_methodid-bp->first_methodid)*sizeof(rhope_func));
329 free(temp);
330 bp->first_methodid = methodid;
331 } else if(methodid >= bp->last_methodid) {
332 //Note: if this gets changed to generating an exception on failure, we need to restore the original buffer
333 bp->method_lookup = realloc(bp->method_lookup, (methodid+1-bp->first_methodid) * sizeof(rhope_func));
334 if(!bp->method_lookup) {
335 fprintf(stderr, "Couldn't resize method lookup table to %d bytes\n", (methodid+1-bp->first_methodid) * sizeof(rhope_func));
336 exit(-1);
337 }
338 memset(bp->method_lookup+bp->last_methodid, '\0', (methodid+1)-bp->last_methodid);
339 bp->last_methodid = methodid;
340 }
341 }
342 bp->method_lookup[methodid-bp->first_methodid] = impl;
343 }