| 
									
										
										
										
											2013-05-11 21:50:21 -04:00
										 |  |  | namespace factor { | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* The compiled code heap is structured into blocks. */ | 
					
						
							| 
									
										
										
										
											2013-05-11 21:50:21 -04:00
										 |  |  | struct code_block { | 
					
						
							|  |  |  |   // header format (bits indexed with least significant as zero):
 | 
					
						
							|  |  |  |   // bit   0  : free?
 | 
					
						
							|  |  |  |   // bits  1-2: type (as a code_block_type)
 | 
					
						
							|  |  |  |   // if not free:
 | 
					
						
							|  |  |  |   //   bits  3-23: code size / 8
 | 
					
						
							|  |  |  |   //   bits 24-31: stack frame size / 16
 | 
					
						
							|  |  |  |   // if free:
 | 
					
						
							|  |  |  |   //   bits  3-end: code size / 8
 | 
					
						
							|  |  |  |   cell header; | 
					
						
							|  |  |  |   cell owner;      /* tagged pointer to word, quotation or f */ | 
					
						
							|  |  |  |   cell parameters; /* tagged pointer to array or f */ | 
					
						
							|  |  |  |   cell relocation; /* tagged pointer to byte-array or f */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   bool free_p() const { return (header & 1) == 1; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   code_block_type type() const { | 
					
						
							|  |  |  |     return (code_block_type)((header >> 1) & 0x3); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void set_type(code_block_type type) { | 
					
						
							|  |  |  |     header = ((header & ~0x7) | (type << 1)); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   bool pic_p() const { return type() == code_block_pic; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   bool optimized_p() const { return type() == code_block_optimized; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   cell size() const { | 
					
						
							|  |  |  |     cell size; | 
					
						
							|  |  |  |     if (free_p()) | 
					
						
							|  |  |  |       size = header & ~7; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       size = header & 0xFFFFF8; | 
					
						
							|  |  |  |     FACTOR_ASSERT(size > 0); | 
					
						
							|  |  |  |     return size; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   cell stack_frame_size() const { | 
					
						
							|  |  |  |     if (free_p()) | 
					
						
							|  |  |  |       return 0; | 
					
						
							| 
									
										
										
										
											2015-08-14 16:31:04 -04:00
										 |  |  |     return (header >> 20) & 0xFF0; | 
					
						
							| 
									
										
										
										
											2013-05-11 21:50:21 -04:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   cell stack_frame_size_for_address(cell addr) const { | 
					
						
							|  |  |  |     cell natural_frame_size = stack_frame_size(); | 
					
						
							|  |  |  |     /* The first instruction in a code block is the prolog safepoint,
 | 
					
						
							|  |  |  |        and a leaf procedure code block will record a frame size of zero. | 
					
						
							|  |  |  |        If we're seeing a stack frame in either of these cases, it's a | 
					
						
							|  |  |  |        fake "leaf frame" set up by the signal handler. */ | 
					
						
							| 
									
										
										
										
											2015-01-07 05:51:19 -05:00
										 |  |  |     if (natural_frame_size == 0 || addr == entry_point()) | 
					
						
							| 
									
										
										
										
											2013-05-11 21:50:21 -04:00
										 |  |  |       return LEAF_FRAME_SIZE; | 
					
						
							| 
									
										
										
										
											2015-08-14 16:31:04 -04:00
										 |  |  |     return natural_frame_size; | 
					
						
							| 
									
										
										
										
											2013-05-11 21:50:21 -04:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void set_stack_frame_size(cell frame_size) { | 
					
						
							|  |  |  |     FACTOR_ASSERT(size() < 0xFFFFFF); | 
					
						
							|  |  |  |     FACTOR_ASSERT(!free_p()); | 
					
						
							|  |  |  |     FACTOR_ASSERT(frame_size % 16 == 0); | 
					
						
							|  |  |  |     FACTOR_ASSERT(frame_size <= 0xFF0); | 
					
						
							|  |  |  |     header = (header & 0xFFFFFF) | (frame_size << 20); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   template <typename Fixup> cell size(Fixup fixup) const { return size(); } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-07 05:51:19 -05:00
										 |  |  |   cell entry_point() const { return (cell)(this + 1); } | 
					
						
							| 
									
										
										
										
											2013-05-11 21:50:21 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* GC info is stored at the end of the block */ | 
					
						
							|  |  |  |   gc_info* block_gc_info() const { | 
					
						
							| 
									
										
										
										
											2013-05-13 00:28:25 -04:00
										 |  |  |     return (gc_info*)((uint8_t*)this + size() - sizeof(gc_info)); | 
					
						
							| 
									
										
										
										
											2013-05-11 21:50:21 -04:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-13 00:53:47 -04:00
										 |  |  |   void flush_icache() { factor::flush_icache((cell)this, size()); } | 
					
						
							| 
									
										
										
										
											2013-05-11 21:50:21 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |   template <typename Iterator> void each_instruction_operand(Iterator& iter) { | 
					
						
							| 
									
										
										
										
											2015-11-22 20:27:22 -05:00
										 |  |  |     if (!to_boolean(relocation)) | 
					
						
							|  |  |  |       return; | 
					
						
							| 
									
										
										
										
											2013-05-11 21:50:21 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-24 10:00:50 -05:00
										 |  |  |     byte_array* rels = untag<byte_array>(relocation); | 
					
						
							| 
									
										
										
										
											2013-05-11 21:50:21 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-22 20:27:22 -05:00
										 |  |  |     cell index = 0; | 
					
						
							| 
									
										
										
										
											2016-03-30 18:06:35 -04:00
										 |  |  |     cell length = untag_fixnum(rels->capacity) / sizeof(relocation_entry); | 
					
						
							| 
									
										
										
										
											2015-11-22 20:27:22 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for (cell i = 0; i < length; i++) { | 
					
						
							|  |  |  |       relocation_entry rel = rels->data<relocation_entry>()[i]; | 
					
						
							|  |  |  |       iter(instruction_operand(rel, this, index)); | 
					
						
							|  |  |  |       index += rel.number_of_parameters(); | 
					
						
							| 
									
										
										
										
											2013-05-11 21:50:21 -04:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-07 05:51:19 -05:00
										 |  |  |   cell offset(cell addr) const { return addr - entry_point(); } | 
					
						
							| 
									
										
										
										
											2013-05-11 21:50:21 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-05 08:04:12 -05:00
										 |  |  |   cell address_for_offset(cell offset) const { | 
					
						
							| 
									
										
										
										
											2015-01-07 05:51:19 -05:00
										 |  |  |     return entry_point() + offset; | 
					
						
							| 
									
										
										
										
											2013-05-11 21:50:21 -04:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-05 08:04:12 -05:00
										 |  |  |   cell scan(factor_vm* vm, cell addr) const; | 
					
						
							| 
									
										
										
										
											2013-05-11 21:50:21 -04:00
										 |  |  |   cell owner_quot() const; | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-12 03:56:24 -04:00
										 |  |  | VM_C_API void undefined_symbol(void); | 
					
						
							| 
									
										
										
										
											2011-11-10 19:00:47 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 21:50:21 -04:00
										 |  |  | inline code_block* word::code() const { | 
					
						
							| 
									
										
										
										
											2015-01-07 05:51:19 -05:00
										 |  |  |   FACTOR_ASSERT(entry_point != 0); | 
					
						
							| 
									
										
										
										
											2013-05-11 21:50:21 -04:00
										 |  |  |   return (code_block*)entry_point - 1; | 
					
						
							| 
									
										
										
										
											2011-11-10 19:00:47 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 21:50:21 -04:00
										 |  |  | inline code_block* quotation::code() const { | 
					
						
							| 
									
										
										
										
											2015-01-07 05:51:19 -05:00
										 |  |  |   FACTOR_ASSERT(entry_point != 0); | 
					
						
							| 
									
										
										
										
											2013-05-11 21:50:21 -04:00
										 |  |  |   return (code_block*)entry_point - 1; | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2011-11-10 19:00:47 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | } |