| | 1 | /* $Header$ */ |
| | 2 | |
| | 3 | /* |
| | 4 | * Copyright (c) 1999, 2002 Michael J. Roberts. All Rights Reserved. |
| | 5 | * |
| | 6 | * Please see the accompanying license file, LICENSE.TXT, for information |
| | 7 | * on using and copying this software. |
| | 8 | */ |
| | 9 | /* |
| | 10 | Name |
| | 11 | vmimgrb.h - image rebuilder |
| | 12 | Function |
| | 13 | Re-builds an image file from the loaded program's state. Useful |
| | 14 | for writing an image file after pre-initialization has bee completed. |
| | 15 | Notes |
| | 16 | |
| | 17 | Modified |
| | 18 | 07/21/99 MJRoberts - Creation |
| | 19 | */ |
| | 20 | |
| | 21 | #ifndef VMIMGRB_H |
| | 22 | #define VMIMGRB_H |
| | 23 | |
| | 24 | #include "vmtype.h" |
| | 25 | |
| | 26 | /* ------------------------------------------------------------------------ */ |
| | 27 | /* |
| | 28 | * Rewrite the image file. Copies an original image file to the given |
| | 29 | * file. |
| | 30 | */ |
| | 31 | void vm_rewrite_image(VMG_ CVmFile *origfp, CVmFile *newfp, |
| | 32 | ulong static_cs_start_ofs); |
| | 33 | |
| | 34 | |
| | 35 | /* ------------------------------------------------------------------------ */ |
| | 36 | /* |
| | 37 | * Object-to-Constant Mapper. |
| | 38 | * |
| | 39 | * When we're rebuilding an image file, we might want to convert all |
| | 40 | * string and list objects (i.e., instances of metaclass String or List) |
| | 41 | * into constant string and list values, respectively, adding these |
| | 42 | * values to the image file's constant pool rather than storing them as |
| | 43 | * object instances. Using constant pool data in an image file |
| | 44 | * increases a program's efficiency by reducing the number of active |
| | 45 | * instances required at run-time. |
| | 46 | * |
| | 47 | * During the conversion process, we need to store the constant data |
| | 48 | * that will go in the additional constant pool pages. We also need to |
| | 49 | * maintain a translation table that gives us the constant pool address |
| | 50 | * of each converted string or list value given its object ID. This |
| | 51 | * object maintains these tables. |
| | 52 | */ |
| | 53 | |
| | 54 | class CVmConstMapper |
| | 55 | { |
| | 56 | public: |
| | 57 | CVmConstMapper(VMG0_); |
| | 58 | ~CVmConstMapper(); |
| | 59 | |
| | 60 | /* |
| | 61 | * Get an object's constant pool address. Returns zero if the |
| | 62 | * object does not have an address mapped yet. |
| | 63 | */ |
| | 64 | ulong get_pool_addr(vm_obj_id_t obj_id); |
| | 65 | |
| | 66 | /* |
| | 67 | * Reserve space for an object's data in the new constant pool. |
| | 68 | * Returns the constant pool address of the reserved space, and adds |
| | 69 | * a translation mapping for the object to our table, so that future |
| | 70 | * calls to get_pool_addr(obj_id) will return this address. |
| | 71 | * |
| | 72 | * If the object is too large to fit on a constant pool page, we'll |
| | 73 | * return zero to indicate that the object cannot be stored in the |
| | 74 | * constant pool; in this case, the object must remain an object |
| | 75 | * instance rather than a constant item. |
| | 76 | * |
| | 77 | * This doesn't actually copy any data, but merely reserves space. |
| | 78 | */ |
| | 79 | ulong alloc_pool_space(vm_obj_id_t obj_id, size_t len); |
| | 80 | |
| | 81 | /* |
| | 82 | * Prepare to begin storing data. This must be called once, after |
| | 83 | * all pool space has been reserved and before the first object's |
| | 84 | * data are actually stored. |
| | 85 | */ |
| | 86 | void prepare_to_store_data(); |
| | 87 | |
| | 88 | /* |
| | 89 | * Store the object's data in its pre-reserved space in the rebuilt |
| | 90 | * constant pool. The space must have previously been allocated |
| | 91 | * with alloc_pool_space(), and the size used must be exactly the |
| | 92 | * same as the space allocated originally. |
| | 93 | */ |
| | 94 | void store_data(vm_obj_id_t obj_id, const void *ptr, size_t len); |
| | 95 | |
| | 96 | /* |
| | 97 | * get the number of pages we've stored - this is valid only after |
| | 98 | * prepare_to_store_data() has been called |
| | 99 | */ |
| | 100 | size_t get_page_count() const { return pages_cnt_; } |
| | 101 | |
| | 102 | /* |
| | 103 | * Write our pages to an image file. This routine can be called |
| | 104 | * only after all of the objects have been stored in the constant |
| | 105 | * pool. |
| | 106 | */ |
| | 107 | void write_to_image_file(class CVmImageWriter *writer, uchar xor_mask); |
| | 108 | |
| | 109 | protected: |
| | 110 | /* |
| | 111 | * Determine how many extra pages we need to add to the original |
| | 112 | * image file's constant pool for our mapped data. |
| | 113 | */ |
| | 114 | size_t calc_page_count() const |
| | 115 | { |
| | 116 | /* |
| | 117 | * calculate the total number of pages by dividing the page size |
| | 118 | * into the total number of bytes we've allocated, rounded up to |
| | 119 | * the next page whole page |
| | 120 | */ |
| | 121 | return (size_t)((next_free_ + (page_size_ - 1) - base_addr_) |
| | 122 | / page_size_); |
| | 123 | } |
| | 124 | |
| | 125 | /* |
| | 126 | * index of our first page - this will be the next page after the |
| | 127 | * last page used in the original image file |
| | 128 | */ |
| | 129 | size_t first_page_idx_; |
| | 130 | |
| | 131 | /* constant pool page size */ |
| | 132 | size_t page_size_; |
| | 133 | |
| | 134 | /* first address that we allocated */ |
| | 135 | ulong base_addr_; |
| | 136 | |
| | 137 | /* next free address for the allocation pass */ |
| | 138 | ulong next_free_; |
| | 139 | |
| | 140 | /* amount of space remaining on current pool allocation page */ |
| | 141 | size_t rem_; |
| | 142 | |
| | 143 | /* |
| | 144 | * Translation page array - each element of this array points to a |
| | 145 | * page that contains 1024 object ID translations. |
| | 146 | */ |
| | 147 | ulong **obj_addr_; |
| | 148 | |
| | 149 | /* number of page slots in obj_addr_ array */ |
| | 150 | size_t obj_addr_cnt_; |
| | 151 | |
| | 152 | /* |
| | 153 | * constant pool page data - we allocate the pages in |
| | 154 | * prepare_to_store_data(), which is called after we know how many |
| | 155 | * pages we'll need |
| | 156 | */ |
| | 157 | struct vm_const_mapper_page **pages_; |
| | 158 | size_t pages_cnt_; |
| | 159 | }; |
| | 160 | |
| | 161 | /* |
| | 162 | * mapper constant pool page |
| | 163 | */ |
| | 164 | struct vm_const_mapper_page |
| | 165 | { |
| | 166 | /* |
| | 167 | * high-water mark for data stored in the page, as an offset from |
| | 168 | * the start of the page's data |
| | 169 | */ |
| | 170 | size_t max_ofs_used; |
| | 171 | |
| | 172 | /* the page's data */ |
| | 173 | char buf[1]; |
| | 174 | }; |
| | 175 | |
| | 176 | |
| | 177 | #endif /* VMIMGRB_H */ |