4 void box_boolean(bool value
)
10 bool to_boolean(CELL value
)
15 CELL
clone_object(CELL object
)
17 CELL size
= object_size(object
);
22 REGISTER_ROOT(object
);
23 void *new_obj
= allot_object(type_of(object
),size
);
24 UNREGISTER_ROOT(object
);
26 CELL tag
= TAG(object
);
27 memcpy(new_obj
,(void*)UNTAG(object
),size
);
28 return RETAG(new_obj
,tag
);
32 void primitive_clone(void)
34 drepl(clone_object(dpeek()));
37 F_WORD
*allot_word(CELL vocab
, CELL name
)
41 F_WORD
*word
= allot_object(WORD_TYPE
,sizeof(F_WORD
));
42 UNREGISTER_ROOT(name
);
43 UNREGISTER_ROOT(vocab
);
45 word
->hashcode
= tag_fixnum((rand() << 16) ^ rand());
46 word
->vocabulary
= vocab
;
48 word
->def
= userenv
[UNDEFINED_ENV
];
50 word
->counter
= tag_fixnum(0);
52 word
->subprimitive
= F
;
53 word
->profiling
= NULL
;
56 REGISTER_UNTAGGED(word
);
57 default_word_code(word
,true);
58 UNREGISTER_UNTAGGED(word
);
60 REGISTER_UNTAGGED(word
);
62 UNREGISTER_UNTAGGED(word
);
65 relocate_code_block(word
->profiling
);
70 /* <word> ( name vocabulary -- word ) */
71 void primitive_word(void)
75 dpush(tag_object(allot_word(vocab
,name
)));
78 /* word-xt ( word -- start end ) */
79 void primitive_word_xt(void)
81 F_WORD
*word
= untag_word(dpop());
82 F_CODE_BLOCK
*code
= (profiling_p
? word
->profiling
: word
->code
);
83 dpush(allot_cell((CELL
)code
+ sizeof(F_CODE_BLOCK
)));
84 dpush(allot_cell((CELL
)code
+ sizeof(F_CODE_BLOCK
) + code
->code_length
));
87 void primitive_wrapper(void)
89 F_WRAPPER
*wrapper
= allot_object(WRAPPER_TYPE
,sizeof(F_WRAPPER
));
90 wrapper
->object
= dpeek();
91 drepl(tag_object(wrapper
));
96 /* the array is full of undefined data, and must be correctly filled before the
97 next GC. size is in cells */
98 F_ARRAY
*allot_array_internal(CELL type
, CELL capacity
)
100 F_ARRAY
*array
= allot_object(type
,array_size(capacity
));
101 array
->capacity
= tag_fixnum(capacity
);
105 /* make a new array with an initial element */
106 F_ARRAY
*allot_array(CELL type
, CELL capacity
, CELL fill
)
110 F_ARRAY
* array
= allot_array_internal(type
, capacity
);
111 UNREGISTER_ROOT(fill
);
113 memset((void*)AREF(array
,0),'\0',capacity
* CELLS
);
116 /* No need for write barrier here. Either the object is in
117 the nursery, or it was allocated directly in tenured space
118 and the write barrier is already hit for us in that case. */
119 for(i
= 0; i
< capacity
; i
++)
120 put(AREF(array
,i
),fill
);
125 /* push a new array on the stack */
126 void primitive_array(void)
128 CELL initial
= dpop();
129 CELL size
= unbox_array_size();
130 dpush(tag_object(allot_array(ARRAY_TYPE
,size
,initial
)));
133 CELL
allot_array_1(CELL obj
)
136 F_ARRAY
*a
= allot_array_internal(ARRAY_TYPE
,1);
137 UNREGISTER_ROOT(obj
);
138 set_array_nth(a
,0,obj
);
139 return tag_object(a
);
142 CELL
allot_array_4(CELL v1
, CELL v2
, CELL v3
, CELL v4
)
148 F_ARRAY
*a
= allot_array_internal(ARRAY_TYPE
,4);
153 set_array_nth(a
,0,v1
);
154 set_array_nth(a
,1,v2
);
155 set_array_nth(a
,2,v3
);
156 set_array_nth(a
,3,v4
);
157 return tag_object(a
);
160 F_ARRAY
*reallot_array(F_ARRAY
* array
, CELL capacity
)
162 CELL to_copy
= array_capacity(array
);
163 if(capacity
< to_copy
)
166 REGISTER_UNTAGGED(array
);
167 F_ARRAY
* new_array
= allot_array_internal(untag_header(array
->header
),capacity
);
168 UNREGISTER_UNTAGGED(array
);
170 memcpy(new_array
+ 1,array
+ 1,to_copy
* CELLS
);
171 memset((char *)AREF(new_array
,to_copy
),'\0',(capacity
- to_copy
) * CELLS
);
176 void primitive_resize_array(void)
178 F_ARRAY
* array
= untag_array(dpop());
179 CELL capacity
= unbox_array_size();
180 dpush(tag_object(reallot_array(array
,capacity
)));
183 F_ARRAY
*growable_array_add(F_ARRAY
*result
, CELL elt
, CELL
*result_count
)
187 if(*result_count
== array_capacity(result
))
189 result
= reallot_array(result
,*result_count
* 2);
192 UNREGISTER_ROOT(elt
);
193 set_array_nth(result
,*result_count
,elt
);
199 F_ARRAY
*growable_array_append(F_ARRAY
*result
, F_ARRAY
*elts
, CELL
*result_count
)
201 REGISTER_UNTAGGED(elts
);
203 CELL elts_size
= array_capacity(elts
);
204 CELL new_size
= *result_count
+ elts_size
;
206 if(new_size
>= array_capacity(result
))
207 result
= reallot_array(result
,new_size
* 2);
209 UNREGISTER_UNTAGGED(elts
);
211 write_barrier((CELL
)result
);
213 memcpy((void *)AREF(result
,*result_count
),(void *)AREF(elts
,0),elts_size
* CELLS
);
215 *result_count
+= elts_size
;
222 /* must fill out array before next GC */
223 F_BYTE_ARRAY
*allot_byte_array_internal(CELL size
)
225 F_BYTE_ARRAY
*array
= allot_object(BYTE_ARRAY_TYPE
,
226 byte_array_size(size
));
227 array
->capacity
= tag_fixnum(size
);
231 /* size is in bytes this time */
232 F_BYTE_ARRAY
*allot_byte_array(CELL size
)
234 F_BYTE_ARRAY
*array
= allot_byte_array_internal(size
);
235 memset(array
+ 1,0,size
);
239 /* push a new byte array on the stack */
240 void primitive_byte_array(void)
242 CELL size
= unbox_array_size();
243 dpush(tag_object(allot_byte_array(size
)));
246 void primitive_uninitialized_byte_array(void)
248 CELL size
= unbox_array_size();
249 dpush(tag_object(allot_byte_array_internal(size
)));
252 F_BYTE_ARRAY
*reallot_byte_array(F_BYTE_ARRAY
*array
, CELL capacity
)
254 CELL to_copy
= array_capacity(array
);
255 if(capacity
< to_copy
)
258 REGISTER_UNTAGGED(array
);
259 F_BYTE_ARRAY
*new_array
= allot_byte_array_internal(capacity
);
260 UNREGISTER_UNTAGGED(array
);
262 memcpy(new_array
+ 1,array
+ 1,to_copy
);
267 void primitive_resize_byte_array(void)
269 F_BYTE_ARRAY
* array
= untag_byte_array(dpop());
270 CELL capacity
= unbox_array_size();
271 dpush(tag_object(reallot_byte_array(array
,capacity
)));
274 F_BYTE_ARRAY
*growable_byte_array_append(F_BYTE_ARRAY
*result
, void *elts
, CELL len
, CELL
*result_count
)
276 CELL new_size
= *result_count
+ len
;
278 if(new_size
>= byte_array_capacity(result
))
279 result
= reallot_byte_array(result
,new_size
* 2);
281 memcpy((void *)BREF(result
,*result_count
),elts
,len
);
283 *result_count
= new_size
;
290 /* push a new tuple on the stack */
291 F_TUPLE
*allot_tuple(F_TUPLE_LAYOUT
*layout
)
293 REGISTER_UNTAGGED(layout
);
294 F_TUPLE
*tuple
= allot_object(TUPLE_TYPE
,tuple_size(layout
));
295 UNREGISTER_UNTAGGED(layout
);
296 tuple
->layout
= tag_object(layout
);
300 void primitive_tuple(void)
302 F_TUPLE_LAYOUT
*layout
= untag_object(dpop());
303 F_FIXNUM size
= untag_fixnum_fast(layout
->size
);
305 F_TUPLE
*tuple
= allot_tuple(layout
);
307 for(i
= size
- 1; i
>= 0; i
--)
308 put(AREF(tuple
,i
),F
);
310 dpush(tag_tuple(tuple
));
313 /* push a new tuple on the stack, filling its slots from the stack */
314 void primitive_tuple_boa(void)
316 F_TUPLE_LAYOUT
*layout
= untag_object(dpop());
317 F_FIXNUM size
= untag_fixnum_fast(layout
->size
);
318 F_TUPLE
*tuple
= allot_tuple(layout
);
319 memcpy(tuple
+ 1,(CELL
*)(ds
- CELLS
* (size
- 1)),CELLS
* size
);
321 dpush(tag_tuple(tuple
));
325 CELL
string_nth(F_STRING
* string
, CELL index
)
327 /* If high bit is set, the most significant 16 bits of the char
328 come from the aux vector. The least significant bit of the
329 corresponding aux vector entry is negated, so that we can
330 XOR the two components together and get the original code point
332 CELL ch
= bget(SREF(string
,index
));
337 F_BYTE_ARRAY
*aux
= untag_object(string
->aux
);
338 return (cget(BREF(aux
,index
* sizeof(u16
))) << 7) ^ ch
;
342 void set_string_nth_fast(F_STRING
* string
, CELL index
, CELL ch
)
344 bput(SREF(string
,index
),ch
);
347 void set_string_nth_slow(F_STRING
* string
, CELL index
, CELL ch
)
351 bput(SREF(string
,index
),(ch
& 0x7f) | 0x80);
355 REGISTER_UNTAGGED(string
);
356 /* We don't need to pre-initialize the
357 byte array with any data, since we
358 only ever read from the aux vector
359 if the most significant bit of a
360 character is set. Initially all of
361 the bits are clear. */
362 aux
= allot_byte_array_internal(
363 untag_fixnum_fast(string
->length
)
365 UNREGISTER_UNTAGGED(string
);
367 write_barrier((CELL
)string
);
368 string
->aux
= tag_object(aux
);
371 aux
= untag_object(string
->aux
);
373 cput(BREF(aux
,index
* sizeof(u16
)),(ch
>> 7) ^ 1);
376 /* allocates memory */
377 void set_string_nth(F_STRING
* string
, CELL index
, CELL ch
)
380 set_string_nth_fast(string
,index
,ch
);
382 set_string_nth_slow(string
,index
,ch
);
386 F_STRING
* allot_string_internal(CELL capacity
)
388 F_STRING
*string
= allot_object(STRING_TYPE
,string_size(capacity
));
390 string
->length
= tag_fixnum(capacity
);
391 string
->hashcode
= F
;
397 /* allocates memory */
398 void fill_string(F_STRING
*string
, CELL start
, CELL capacity
, CELL fill
)
401 memset((void *)SREF(string
,start
),fill
,capacity
- start
);
406 for(i
= start
; i
< capacity
; i
++)
408 REGISTER_UNTAGGED(string
);
409 set_string_nth(string
,i
,fill
);
410 UNREGISTER_UNTAGGED(string
);
416 F_STRING
*allot_string(CELL capacity
, CELL fill
)
418 F_STRING
* string
= allot_string_internal(capacity
);
419 REGISTER_UNTAGGED(string
);
420 fill_string(string
,0,capacity
,fill
);
421 UNREGISTER_UNTAGGED(string
);
425 void primitive_string(void)
427 CELL initial
= to_cell(dpop());
428 CELL length
= unbox_array_size();
429 dpush(tag_object(allot_string(length
,initial
)));
432 F_STRING
* reallot_string(F_STRING
* string
, CELL capacity
)
434 CELL to_copy
= string_capacity(string
);
435 if(capacity
< to_copy
)
438 REGISTER_UNTAGGED(string
);
439 F_STRING
*new_string
= allot_string_internal(capacity
);
440 UNREGISTER_UNTAGGED(string
);
442 memcpy(new_string
+ 1,string
+ 1,to_copy
);
446 REGISTER_UNTAGGED(string
);
447 REGISTER_UNTAGGED(new_string
);
448 F_BYTE_ARRAY
*new_aux
= allot_byte_array(capacity
* sizeof(u16
));
449 UNREGISTER_UNTAGGED(new_string
);
450 UNREGISTER_UNTAGGED(string
);
452 write_barrier((CELL
)new_string
);
453 new_string
->aux
= tag_object(new_aux
);
455 F_BYTE_ARRAY
*aux
= untag_object(string
->aux
);
456 memcpy(new_aux
+ 1,aux
+ 1,to_copy
* sizeof(u16
));
459 REGISTER_UNTAGGED(string
);
460 REGISTER_UNTAGGED(new_string
);
461 fill_string(new_string
,to_copy
,capacity
,'\0');
462 UNREGISTER_UNTAGGED(new_string
);
463 UNREGISTER_UNTAGGED(string
);
468 void primitive_resize_string(void)
470 F_STRING
* string
= untag_string(dpop());
471 CELL capacity
= unbox_array_size();
472 dpush(tag_object(reallot_string(string
,capacity
)));
475 /* Some ugly macros to prevent a 2x code duplication */
477 #define MEMORY_TO_STRING(type,utype) \
478 F_STRING *memory_to_##type##_string(const type *string, CELL length) \
480 REGISTER_C_STRING(string); \
481 F_STRING* s = allot_string_internal(length); \
482 UNREGISTER_C_STRING(string); \
484 for(i = 0; i < length; i++) \
486 REGISTER_UNTAGGED(s); \
487 set_string_nth(s,i,(utype)*string); \
488 UNREGISTER_UNTAGGED(s); \
493 F_STRING *from_##type##_string(const type *str) \
496 const type *scan = str; \
497 while(*scan++) length++; \
498 return memory_to_##type##_string(str,length); \
500 void box_##type##_string(const type *str) \
502 dpush(str ? tag_object(from_##type##_string(str)) : F); \
505 MEMORY_TO_STRING(char,u8
)
506 MEMORY_TO_STRING(u16
,u16
)
507 MEMORY_TO_STRING(u32
,u32
)
509 bool check_string(F_STRING
*s
, CELL max
)
511 CELL capacity
= string_capacity(s
);
513 for(i
= 0; i
< capacity
; i
++)
515 CELL ch
= string_nth(s
,i
);
516 if(ch
== '\0' || ch
>= (1 << (max
* 8)))
522 F_BYTE_ARRAY
*allot_c_string(CELL capacity
, CELL size
)
524 return allot_byte_array((capacity
+ 1) * size
);
527 #define STRING_TO_MEMORY(type) \
528 void type##_string_to_memory(F_STRING *s, type *string) \
531 CELL capacity = string_capacity(s); \
532 for(i = 0; i < capacity; i++) \
533 string[i] = string_nth(s,i); \
535 void primitive_##type##_string_to_memory(void) \
537 type *address = unbox_alien(); \
538 F_STRING *str = untag_string(dpop()); \
539 type##_string_to_memory(str,address); \
541 F_BYTE_ARRAY *string_to_##type##_alien(F_STRING *s, bool check) \
543 CELL capacity = string_capacity(s); \
544 F_BYTE_ARRAY *_c_str; \
545 if(check && !check_string(s,sizeof(type))) \
546 general_error(ERROR_C_STRING,tag_object(s),F,NULL); \
547 REGISTER_UNTAGGED(s); \
548 _c_str = allot_c_string(capacity,sizeof(type)); \
549 UNREGISTER_UNTAGGED(s); \
550 type *c_str = (type*)(_c_str + 1); \
551 type##_string_to_memory(s,c_str); \
552 c_str[capacity] = 0; \
555 type *to_##type##_string(F_STRING *s, bool check) \
557 return (type*)(string_to_##type##_alien(s,check) + 1); \
559 type *unbox_##type##_string(void) \
561 return to_##type##_string(untag_string(dpop()),true); \
564 STRING_TO_MEMORY(char);
565 STRING_TO_MEMORY(u16
);
567 void primitive_string_nth(void)
569 F_STRING
*string
= untag_object(dpop());
570 CELL index
= untag_fixnum_fast(dpop());
571 dpush(tag_fixnum(string_nth(string
,index
)));
574 void primitive_set_string_nth(void)
576 F_STRING
*string
= untag_object(dpop());
577 CELL index
= untag_fixnum_fast(dpop());
578 CELL value
= untag_fixnum_fast(dpop());
579 set_string_nth(string
,index
,value
);
582 void primitive_set_string_nth_fast(void)
584 F_STRING
*string
= untag_object(dpop());
585 CELL index
= untag_fixnum_fast(dpop());
586 CELL value
= untag_fixnum_fast(dpop());
587 set_string_nth_fast(string
,index
,value
);
590 void primitive_set_string_nth_slow(void)
592 F_STRING
*string
= untag_object(dpop());
593 CELL index
= untag_fixnum_fast(dpop());
594 CELL value
= untag_fixnum_fast(dpop());
595 set_string_nth_slow(string
,index
,value
);