| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | #include "master.hpp"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 21:40:43 -04:00
										 |  |  | namespace factor { | 
					
						
							| 
									
										
										
										
											2009-05-04 02:46:13 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | /* gets the address of an object representing a C pointer, with the
 | 
					
						
							|  |  |  | intention of storing the pointer across code which may potentially GC. */ | 
					
						
							| 
									
										
										
										
											2013-05-11 21:40:43 -04:00
										 |  |  | char* factor_vm::pinned_alien_offset(cell obj) { | 
					
						
							|  |  |  |   switch (tagged<object>(obj).type()) { | 
					
						
							|  |  |  |     case ALIEN_TYPE: { | 
					
						
							|  |  |  |       alien* ptr = untag<alien>(obj); | 
					
						
							|  |  |  |       if (to_boolean(ptr->expired)) | 
					
						
							|  |  |  |         general_error(ERROR_EXPIRED, obj, false_object); | 
					
						
							|  |  |  |       if (to_boolean(ptr->base)) | 
					
						
							|  |  |  |         type_error(ALIEN_TYPE, obj); | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         return (char*)ptr->address; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case F_TYPE: | 
					
						
							|  |  |  |       return NULL; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       type_error(ALIEN_TYPE, obj); | 
					
						
							|  |  |  |       return NULL; /* can't happen */ | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* make an alien */ | 
					
						
							| 
									
										
										
										
											2013-03-25 14:59:33 -04:00
										 |  |  | /* Allocates memory */ | 
					
						
							| 
									
										
										
										
											2013-05-11 21:40:43 -04:00
										 |  |  | cell factor_vm::allot_alien(cell delegate_, cell displacement) { | 
					
						
							|  |  |  |   if (displacement == 0) | 
					
						
							|  |  |  |     return delegate_; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   data_root<object> delegate(delegate_, this); | 
					
						
							|  |  |  |   data_root<alien> new_alien(allot<alien>(sizeof(alien)), this); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (delegate.type_p(ALIEN_TYPE)) { | 
					
						
							|  |  |  |     tagged<alien> delegate_alien = delegate.as<alien>(); | 
					
						
							|  |  |  |     displacement += delegate_alien->displacement; | 
					
						
							|  |  |  |     new_alien->base = delegate_alien->base; | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |     new_alien->base = delegate.value(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   new_alien->displacement = displacement; | 
					
						
							|  |  |  |   new_alien->expired = false_object; | 
					
						
							|  |  |  |   new_alien->update_address(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return new_alien.value(); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-16 01:00:08 -04:00
										 |  |  | /* Allocates memory */ | 
					
						
							| 
									
										
										
										
											2013-05-11 21:40:43 -04:00
										 |  |  | cell factor_vm::allot_alien(void* address) { | 
					
						
							| 
									
										
										
										
											2013-05-13 00:53:47 -04:00
										 |  |  |   return allot_alien(false_object, (cell)address); | 
					
						
							| 
									
										
										
										
											2009-12-18 16:59:56 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | /* make an alien pointing at an offset of another alien */ | 
					
						
							| 
									
										
										
										
											2013-03-25 14:59:33 -04:00
										 |  |  | /* Allocates memory */ | 
					
						
							| 
									
										
										
										
											2013-05-11 21:40:43 -04:00
										 |  |  | void factor_vm::primitive_displaced_alien() { | 
					
						
							|  |  |  |   cell alien = ctx->pop(); | 
					
						
							|  |  |  |   cell displacement = to_cell(ctx->pop()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   switch (tagged<object>(alien).type()) { | 
					
						
							|  |  |  |     case BYTE_ARRAY_TYPE: | 
					
						
							|  |  |  |     case ALIEN_TYPE: | 
					
						
							|  |  |  |     case F_TYPE: | 
					
						
							|  |  |  |       ctx->push(allot_alien(alien, displacement)); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       type_error(ALIEN_TYPE, alien); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* address of an object representing a C pointer. Explicitly throw an error
 | 
					
						
							|  |  |  | if the object is a byte array, as a sanity check. */ | 
					
						
							| 
									
										
										
										
											2013-03-25 14:59:33 -04:00
										 |  |  | /* Allocates memory (from_unsigned_cell can allocate) */ | 
					
						
							| 
									
										
										
										
											2013-05-11 21:40:43 -04:00
										 |  |  | void factor_vm::primitive_alien_address() { | 
					
						
							| 
									
										
										
										
											2013-05-13 00:53:47 -04:00
										 |  |  |   ctx->replace(from_unsigned_cell((cell)pinned_alien_offset(ctx->peek()))); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* pop ( alien n ) from datastack, return alien's address plus n */ | 
					
						
							| 
									
										
										
										
											2013-05-11 21:40:43 -04:00
										 |  |  | void* factor_vm::alien_pointer() { | 
					
						
							|  |  |  |   fixnum offset = to_fixnum(ctx->pop()); | 
					
						
							|  |  |  |   return alien_offset(ctx->pop()) + offset; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* define words to read/write values at an alien address */ | 
					
						
							| 
									
										
										
										
											2013-05-11 21:40:43 -04:00
										 |  |  | #define DEFINE_ALIEN_ACCESSOR(name, type, from, to)                     \
 | 
					
						
							|  |  |  |   VM_C_API void primitive_alien_##name(factor_vm * parent) {            \ | 
					
						
							|  |  |  |     parent->ctx->push(parent->from(*(type*)(parent->alien_pointer()))); \ | 
					
						
							|  |  |  |   }                                                                     \ | 
					
						
							|  |  |  |   VM_C_API void primitive_set_alien_##name(factor_vm * parent) {        \ | 
					
						
							|  |  |  |     type* ptr = (type*)parent->alien_pointer();                         \ | 
					
						
							| 
									
										
										
										
											2013-05-13 00:53:47 -04:00
										 |  |  |     type value = (type)parent->to(parent->ctx->pop());                  \ | 
					
						
							| 
									
										
										
										
											2013-05-11 21:40:43 -04:00
										 |  |  |     *ptr = value;                                                       \ | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-19 14:05:14 -04:00
										 |  |  | EACH_ALIEN_PRIMITIVE(DEFINE_ALIEN_ACCESSOR) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* open a native library and push a handle */ | 
					
						
							| 
									
										
										
										
											2013-11-28 11:59:45 -05:00
										 |  |  | /* Allocates memory */ | 
					
						
							| 
									
										
										
										
											2013-05-11 21:40:43 -04:00
										 |  |  | void factor_vm::primitive_dlopen() { | 
					
						
							|  |  |  |   data_root<byte_array> path(ctx->pop(), this); | 
					
						
							|  |  |  |   path.untag_check(this); | 
					
						
							|  |  |  |   data_root<dll> library(allot<dll>(sizeof(dll)), this); | 
					
						
							|  |  |  |   library->path = path.value(); | 
					
						
							|  |  |  |   ffi_dlopen(library.untagged()); | 
					
						
							|  |  |  |   ctx->push(library.value()); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* look up a symbol in a native library */ | 
					
						
							| 
									
										
										
										
											2013-03-25 14:59:33 -04:00
										 |  |  | /* Allocates memory */ | 
					
						
							| 
									
										
										
										
											2013-05-11 21:40:43 -04:00
										 |  |  | void factor_vm::primitive_dlsym() { | 
					
						
							|  |  |  |   data_root<object> library(ctx->pop(), this); | 
					
						
							|  |  |  |   data_root<byte_array> name(ctx->peek(), this); | 
					
						
							|  |  |  |   name.untag_check(this); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   symbol_char* sym = name->data<symbol_char>(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (to_boolean(library.value())) { | 
					
						
							|  |  |  |     dll* d = untag_check<dll>(library.value()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (d->handle == NULL) | 
					
						
							|  |  |  |       ctx->replace(false_object); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       ctx->replace(allot_alien(ffi_dlsym(d, sym))); | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |     ctx->replace(allot_alien(ffi_dlsym(NULL, sym))); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-20 18:11:50 -04:00
										 |  |  | /* look up a symbol in a native library */ | 
					
						
							| 
									
										
										
										
											2013-03-25 14:59:33 -04:00
										 |  |  | /* Allocates memory */ | 
					
						
							| 
									
										
										
										
											2013-05-11 21:40:43 -04:00
										 |  |  | void factor_vm::primitive_dlsym_raw() { | 
					
						
							|  |  |  |   data_root<object> library(ctx->pop(), this); | 
					
						
							|  |  |  |   data_root<byte_array> name(ctx->peek(), this); | 
					
						
							|  |  |  |   name.untag_check(this); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   symbol_char* sym = name->data<symbol_char>(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (to_boolean(library.value())) { | 
					
						
							|  |  |  |     dll* d = untag_check<dll>(library.value()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (d->handle == NULL) | 
					
						
							|  |  |  |       ctx->replace(false_object); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       ctx->replace(allot_alien(ffi_dlsym_raw(d, sym))); | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |     ctx->replace(allot_alien(ffi_dlsym_raw(NULL, sym))); | 
					
						
							| 
									
										
										
										
											2011-05-20 18:11:50 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | /* close a native library handle */ | 
					
						
							| 
									
										
										
										
											2013-05-11 21:40:43 -04:00
										 |  |  | void factor_vm::primitive_dlclose() { | 
					
						
							|  |  |  |   dll* d = untag_check<dll>(ctx->pop()); | 
					
						
							|  |  |  |   if (d->handle != NULL) | 
					
						
							|  |  |  |     ffi_dlclose(d); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 21:40:43 -04:00
										 |  |  | void factor_vm::primitive_dll_validp() { | 
					
						
							|  |  |  |   cell library = ctx->peek(); | 
					
						
							|  |  |  |   if (to_boolean(library)) | 
					
						
							|  |  |  |     ctx->replace(tag_boolean(untag_check<dll>(library)->handle != NULL)); | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     ctx->replace(true_object); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-05-04 02:00:30 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* gets the address of an object representing a C pointer */ | 
					
						
							| 
									
										
										
										
											2013-05-11 21:40:43 -04:00
										 |  |  | char* factor_vm::alien_offset(cell obj) { | 
					
						
							|  |  |  |   switch (tagged<object>(obj).type()) { | 
					
						
							|  |  |  |     case BYTE_ARRAY_TYPE: | 
					
						
							|  |  |  |       return untag<byte_array>(obj)->data<char>(); | 
					
						
							|  |  |  |     case ALIEN_TYPE: | 
					
						
							|  |  |  |       return (char*)untag<alien>(obj)->address; | 
					
						
							|  |  |  |     case F_TYPE: | 
					
						
							|  |  |  |       return NULL; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       type_error(ALIEN_TYPE, obj); | 
					
						
							|  |  |  |       return NULL; /* can't happen */ | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2009-05-04 02:00:30 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 02:46:13 -04:00
										 |  |  | } |