| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | #include "master.hpp"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 02:46:13 -04:00
										 |  |  | namespace factor | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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. */ | 
					
						
							| 
									
										
										
										
											2009-09-23 14:05:46 -04:00
										 |  |  | char *factor_vm::pinned_alien_offset(cell obj) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	switch(tagged<object>(obj).type()) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 	case ALIEN_TYPE: | 
					
						
							| 
									
										
										
										
											2009-05-04 08:00:06 -04:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			alien *ptr = untag<alien>(obj); | 
					
						
							| 
									
										
										
										
											2009-10-18 21:26:21 -04:00
										 |  |  | 			if(to_boolean(ptr->expired)) | 
					
						
							| 
									
										
										
										
											2010-03-27 07:33:28 -04:00
										 |  |  | 				general_error(ERROR_EXPIRED,obj,false_object); | 
					
						
							| 
									
										
										
										
											2009-11-02 04:25:39 -05:00
										 |  |  | 			if(to_boolean(ptr->base)) | 
					
						
							|  |  |  | 				type_error(ALIEN_TYPE,obj); | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				return (char *)ptr->address; | 
					
						
							| 
									
										
										
										
											2009-05-04 08:00:06 -04:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	case F_TYPE: | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 		type_error(ALIEN_TYPE,obj); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 		return NULL; /* can't happen */ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* make an alien */ | 
					
						
							| 
									
										
										
										
											2009-09-23 14:05:46 -04:00
										 |  |  | cell factor_vm::allot_alien(cell delegate_, cell displacement) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-04-30 20:14:17 -04:00
										 |  |  | 	if(displacement == 0) | 
					
						
							|  |  |  | 		return delegate_; | 
					
						
							| 
									
										
										
										
											2009-12-18 16:59:56 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-02 19:10:34 -05:00
										 |  |  | 	data_root<object> delegate(delegate_,this); | 
					
						
							|  |  |  | 	data_root<alien> new_alien(allot<alien>(sizeof(alien)),this); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 02:00:30 -04:00
										 |  |  | 	if(delegate.type_p(ALIEN_TYPE)) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 		tagged<alien> delegate_alien = delegate.as<alien>(); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 		displacement += delegate_alien->displacement; | 
					
						
							| 
									
										
										
										
											2009-10-09 04:20:50 -04:00
										 |  |  | 		new_alien->base = delegate_alien->base; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							| 
									
										
										
										
											2009-10-09 04:20:50 -04:00
										 |  |  | 		new_alien->base = delegate.value(); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	new_alien->displacement = displacement; | 
					
						
							| 
									
										
										
										
											2009-10-18 21:26:21 -04:00
										 |  |  | 	new_alien->expired = false_object; | 
					
						
							| 
									
										
										
										
											2009-11-02 04:25:39 -05:00
										 |  |  | 	new_alien->update_address(); | 
					
						
							| 
									
										
										
										
											2009-05-02 10:19:09 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	return new_alien.value(); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-18 16:59:56 -05:00
										 |  |  | cell factor_vm::allot_alien(void *address) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return allot_alien(false_object,(cell)address); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | /* make an alien pointing at an offset of another alien */ | 
					
						
							| 
									
										
										
										
											2009-09-27 14:42:18 -04:00
										 |  |  | void factor_vm::primitive_displaced_alien() | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-12-18 16:59:56 -05:00
										 |  |  | 	cell alien = ctx->pop(); | 
					
						
							|  |  |  | 	cell displacement = to_cell(ctx->pop()); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-18 16:59:56 -05:00
										 |  |  | 	switch(tagged<object>(alien).type()) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-12-18 16:59:56 -05:00
										 |  |  | 	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. */ | 
					
						
							| 
									
										
										
										
											2009-09-27 14:42:18 -04:00
										 |  |  | void factor_vm::primitive_alien_address() | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-19 10:09:28 -04:00
										 |  |  | 	ctx->push(from_unsigned_cell((cell)pinned_alien_offset(ctx->pop()))); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* pop ( alien n ) from datastack, return alien's address plus n */ | 
					
						
							| 
									
										
										
										
											2009-09-23 14:05:46 -04:00
										 |  |  | void *factor_vm::alien_pointer() | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-12-18 16:59:56 -05:00
										 |  |  | 	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 */ | 
					
						
							| 
									
										
										
										
											2009-12-18 16:59:56 -05:00
										 |  |  | #define DEFINE_ALIEN_ACCESSOR(name,type,from,to) \
 | 
					
						
							| 
									
										
										
										
											2010-01-19 08:48:31 -05:00
										 |  |  | 	VM_C_API void primitive_alien_##name(factor_vm *parent) \ | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	{ \ | 
					
						
							| 
									
										
										
										
											2010-05-11 23:24:25 -04:00
										 |  |  | 		parent->ctx->push(parent->from(*(type*)(parent->alien_pointer()))); \ | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	} \ | 
					
						
							| 
									
										
										
										
											2010-01-19 08:48:31 -05:00
										 |  |  | 	VM_C_API void primitive_set_alien_##name(factor_vm *parent) \ | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	{ \ | 
					
						
							| 
									
										
										
										
											2009-10-18 21:31:59 -04:00
										 |  |  | 		type *ptr = (type *)parent->alien_pointer(); \ | 
					
						
							| 
									
										
										
										
											2010-05-11 23:24:25 -04:00
										 |  |  | 		type value = (type)parent->to(parent->ctx->pop()); \ | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 		*ptr = value; \ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 */ | 
					
						
							| 
									
										
										
										
											2009-09-27 14:42:18 -04:00
										 |  |  | void factor_vm::primitive_dlopen() | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-12-18 16:59:56 -05:00
										 |  |  | 	data_root<byte_array> path(ctx->pop(),this); | 
					
						
							| 
									
										
										
										
											2009-08-17 16:37:15 -04:00
										 |  |  | 	path.untag_check(this); | 
					
						
							| 
									
										
										
										
											2009-11-02 19:10:34 -05:00
										 |  |  | 	data_root<dll> library(allot<dll>(sizeof(dll)),this); | 
					
						
							| 
									
										
										
										
											2009-05-04 09:08:33 -04:00
										 |  |  | 	library->path = path.value(); | 
					
						
							|  |  |  | 	ffi_dlopen(library.untagged()); | 
					
						
							| 
									
										
										
										
											2009-12-18 16:59:56 -05:00
										 |  |  | 	ctx->push(library.value()); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* look up a symbol in a native library */ | 
					
						
							| 
									
										
										
										
											2009-09-27 14:42:18 -04:00
										 |  |  | void factor_vm::primitive_dlsym() | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-12-18 16:59:56 -05:00
										 |  |  | 	data_root<object> library(ctx->pop(),this); | 
					
						
							|  |  |  | 	data_root<byte_array> name(ctx->pop(),this); | 
					
						
							| 
									
										
										
										
											2009-08-17 16:37:15 -04:00
										 |  |  | 	name.untag_check(this); | 
					
						
							| 
									
										
										
										
											2009-05-02 14:45:38 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-05 14:03:24 -04:00
										 |  |  | 	symbol_char *sym = name->data<symbol_char>(); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-18 21:26:21 -04:00
										 |  |  | 	if(to_boolean(library.value())) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-07-09 07:51:31 -04:00
										 |  |  | 		dll *d = untag_check<dll>(library.value()); | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-16 09:43:22 -05:00
										 |  |  | 		if(d->handle == NULL) | 
					
						
							| 
									
										
										
										
											2009-12-18 16:59:56 -05:00
										 |  |  | 			ctx->push(false_object); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 		else | 
					
						
							| 
									
										
										
										
											2009-12-18 16:59:56 -05:00
										 |  |  | 			ctx->push(allot_alien(ffi_dlsym(d,sym))); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-10-18 21:26:21 -04:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2009-12-18 16:59:56 -05:00
										 |  |  | 		ctx->push(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 */ | 
					
						
							|  |  |  | void factor_vm::primitive_dlsym_raw() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	data_root<object> library(ctx->pop(),this); | 
					
						
							|  |  |  | 	data_root<byte_array> name(ctx->pop(),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->push(false_object); | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			ctx->push(allot_alien(ffi_dlsym_raw(d,sym))); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		ctx->push(allot_alien(ffi_dlsym_raw(NULL,sym))); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | /* close a native library handle */ | 
					
						
							| 
									
										
										
										
											2009-09-27 14:42:18 -04:00
										 |  |  | void factor_vm::primitive_dlclose() | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-12-18 16:59:56 -05:00
										 |  |  | 	dll *d = untag_check<dll>(ctx->pop()); | 
					
						
							| 
									
										
										
										
											2010-01-16 09:43:22 -05:00
										 |  |  | 	if(d->handle != NULL) | 
					
						
							| 
									
										
										
										
											2009-07-09 07:51:31 -04:00
										 |  |  | 		ffi_dlclose(d); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-27 14:42:18 -04:00
										 |  |  | void factor_vm::primitive_dll_validp() | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-12-18 16:59:56 -05:00
										 |  |  | 	cell library = ctx->pop(); | 
					
						
							| 
									
										
										
										
											2009-10-18 21:26:21 -04:00
										 |  |  | 	if(to_boolean(library)) | 
					
						
							| 
									
										
										
										
											2010-01-16 09:43:22 -05:00
										 |  |  | 		ctx->push(tag_boolean(untag_check<dll>(library)->handle != NULL)); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2009-12-18 16:59:56 -05:00
										 |  |  | 		ctx->push(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 */ | 
					
						
							| 
									
										
										
										
											2009-09-23 14:05:46 -04:00
										 |  |  | char *factor_vm::alien_offset(cell obj) | 
					
						
							| 
									
										
										
										
											2009-05-04 02:00:30 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	switch(tagged<object>(obj).type()) | 
					
						
							| 
									
										
										
										
											2009-05-04 02:00:30 -04:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 	case BYTE_ARRAY_TYPE: | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 		return untag<byte_array>(obj)->data<char>(); | 
					
						
							| 
									
										
										
										
											2009-05-04 02:00:30 -04:00
										 |  |  | 	case ALIEN_TYPE: | 
					
						
							| 
									
										
										
										
											2009-11-02 04:25:39 -05:00
										 |  |  | 		return (char *)untag<alien>(obj)->address; | 
					
						
							| 
									
										
										
										
											2009-05-04 02:00:30 -04:00
										 |  |  | 	case F_TYPE: | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 		type_error(ALIEN_TYPE,obj); | 
					
						
							| 
									
										
										
										
											2009-05-04 02:00:30 -04:00
										 |  |  | 		return NULL; /* can't happen */ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 02:46:13 -04:00
										 |  |  | } |