| 
									
										
										
										
											2009-10-16 12:39:22 -04:00
										 |  |  | namespace factor | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | /* The callback heap is used to store the machine code that alien-callbacks
 | 
					
						
							|  |  |  | actually jump to when C code invokes them. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The callback heap has entries that look like code_blocks from the code heap, | 
					
						
							|  |  |  | but callback heap entries are allocated contiguously, never deallocated, and all | 
					
						
							|  |  |  | fields but the owner are set to false_object. The owner points to the callback | 
					
						
							|  |  |  | bottom word, whose XT is the callback body itself, generated by the optimizing | 
					
						
							|  |  |  | compiler. The machine code that follows a callback stub consists of a single | 
					
						
							|  |  |  | CALLBACK_STUB machine code template, which performs a jump to a "far" address | 
					
						
							|  |  |  | (on PowerPC and x86-64, its loaded into a register first). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GC updates the CALLBACK_STUB code if the code block of the callback bottom word | 
					
						
							|  |  |  | is ever moved. The callback stub itself won't move, though, and is never | 
					
						
							|  |  |  | deallocated. This means that the callback stub itself is a stable function | 
					
						
							|  |  |  | pointer that C code can hold on to until the associated Factor VM exits. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Since callback stubs are GC roots, and are never deallocated, the associated | 
					
						
							|  |  |  | callback code in the code heap is also never deallocated. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The callback heap is not saved in the image. Running GC in a new session after | 
					
						
							|  |  |  | saving the image will deallocate any code heap entries that were only reachable | 
					
						
							|  |  |  | from the callback heap in the previous session when the image was saved. */ | 
					
						
							| 
									
										
										
										
											2009-10-16 12:39:22 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | struct callback_heap { | 
					
						
							|  |  |  | 	segment *seg; | 
					
						
							|  |  |  | 	cell here; | 
					
						
							| 
									
										
										
										
											2009-10-18 21:31:59 -04:00
										 |  |  | 	factor_vm *parent; | 
					
						
							| 
									
										
										
										
											2009-10-16 12:39:22 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-18 21:31:59 -04:00
										 |  |  | 	explicit callback_heap(cell size, factor_vm *parent); | 
					
						
							| 
									
										
										
										
											2009-10-16 12:39:22 -04:00
										 |  |  | 	~callback_heap(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 	void *callback_xt(code_block *stub) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		word *w = (word *)UNTAG(stub->owner); | 
					
						
							|  |  |  | 		return w->xt; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-10 07:20:32 -05:00
										 |  |  | 	void store_callback_operand(code_block *stub, cell index, cell value); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 	void update(code_block *stub); | 
					
						
							| 
									
										
										
										
											2010-01-10 07:20:32 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-02 07:03:30 -05:00
										 |  |  | 	code_block *add(cell owner, cell return_rewind); | 
					
						
							| 
									
										
										
										
											2009-10-16 12:39:22 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-02 04:31:57 -05:00
										 |  |  | 	void update(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 	code_block *next(code_block *stub) | 
					
						
							| 
									
										
										
										
											2009-10-16 12:39:22 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 		return (code_block *)((cell)stub + stub->size()); | 
					
						
							| 
									
										
										
										
											2009-10-16 12:39:22 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 	template<typename Iterator> void each_callback(Iterator &iter) | 
					
						
							| 
									
										
										
										
											2009-10-16 12:39:22 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 		code_block *scan = (code_block *)seg->start; | 
					
						
							|  |  |  | 		code_block *end = (code_block *)here; | 
					
						
							| 
									
										
										
										
											2009-10-16 12:39:22 -04:00
										 |  |  | 		while(scan < end) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			iter(scan); | 
					
						
							|  |  |  | 			scan = next(scan); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |