1 /* VM library: specializer header file. 2 3 Copyright (C) 2016, 2017, 2019, 2020 Luca Saiu 4 Written by Luca Saiu 5 6 This file is part of Jitter. 7 8 Jitter is free software: you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation, either version 3 of the License, or 11 (at your option) any later version. 12 13 Jitter is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with Jitter. If not, see <http://www.gnu.org/licenses/>. */ 20 21 22 #ifndef JITTER_SPECIALIZE_H_ 23 #define JITTER_SPECIALIZE_H_ 24 25 #include <jitter/jitter.h> 26 #include <jitter/jitter-mutable-routine.h> 27 #include <jitter/jitter-instruction.h> 28 29 30 /* Executable routines. 31 * ************************************************************************** */ 32 33 /* An executable routine is a data structure obtained from a routine, with a 34 different internal representation meant for direct execution rather than 35 modificaion -- the internal representation is in fact *very* different, 36 particularly in sophisticated dispatching modes involving native code. 37 38 Only an executable routine can be run on a VM, and only a non-executable 39 routine can be modified by adding instructions and labels. 40 41 Each non-executable routine can generate at most one executable routine. 42 43 Once the executable routine has been generated (thru 44 jitter_make_executable_routine ) the user is free to destroy the original 45 non-executable routine in ordre to free resources, while the executable 46 routine can be safely executed. Destroying a non-executable routine is 47 always allowed but may make disassembly and debugging information less 48 precise. */ 49 50 /* The internal representation of an executable routine. This should be treated 51 as an abstract data type. */ 52 struct jitter_executable_routine 53 { 54 /* The non-executable version of this routine, if one still exists. This 55 field, non-NULL at initialization, becomes NULL if the original 56 non-executable routine is destroyed. */ 57 struct jitter_mutable_routine *routine; 58 59 /* A pointer to the VM this belongs to, which is never invalidated even 60 if the mutable routine is destroyed. */ 61 const struct jitter_vm *vm; 62 63 /* How many live pointers there are to this executable routine. This is set 64 to 1 at initialization, then updated manually with 65 jitter_pin_executable_routine and jitter_unpin_executable_routine , 66 declared below. 67 68 The executable routine is automatically destroyed, along with its companion 69 mutable routine, when the reference count reaches zero. Notice that, by 70 contrast, when the user explicitly destroys an executable routine its 71 mutable companion is *not* automatically destroyed. */ 72 unsigned long reference_count; 73 74 /* The following fields, including the ones conditionalized over the 75 dispatching mode, have the same meaning as the fields with the same name 76 from struct jitter_mutable_routine, and are copied from there. See the comments in 77 jitter-routine.h . 78 The fields represented as struct jitter_dynamic_buffer in struct 79 jitter_routine, for ease of incremental construction, here are simply 80 heap-allocated buffers, whose size will no longer change. In fact their 81 heap storage is the same allocated within struct jitter_mutable_routine, obtained 82 by extraction. The finalization API for struct jitter_mutable_routine keeps this 83 into account, and of course avoids freeing heap memory twice. */ 84 jitter_int slow_register_per_class_no; 85 #if (defined(JITTER_DISPATCH_SWITCH) \ 86 || defined(JITTER_DISPATCH_DIRECT_THREADING) \ 87 || defined(JITTER_DISPATCH_MINIMAL_THREADING)) 88 union jitter_specialized_word *specialized_program; 89 #elif defined(JITTER_DISPATCH_NO_THREADING) 90 /* Nothing. */ 91 #elif ! defined (JITTER_INTERNAL) 92 # error "unknown dispatch: this should not happen" 93 #else 94 /* This is a dispatch-independent compilation, either part of the Jitter 95 utility library or of the C code generator. The specific fields of this 96 struct do not matter. */ 97 #endif /* dispatch */ 98 #if (defined(JITTER_DISPATCH_SWITCH) \ 99 || defined(JITTER_DISPATCH_DIRECT_THREADING)) 100 /* Nothing. */ 101 #elif (defined(JITTER_DISPATCH_MINIMAL_THREADING) \ 102 || defined(JITTER_DISPATCH_NO_THREADING)) 103 char *native_code; 104 size_t native_code_size; 105 #elif ! defined (JITTER_INTERNAL) 106 # error "unknown dispatch: this should not happen" 107 #else 108 /* This is a dispatch-independent compilation, either part of the Jitter 109 utility library or of the C code generator. The specific fields of this 110 struct do not matter. */ 111 #endif /* dispatch */ 112 }; 113 114 /* Translate the pointed routine into a fresh executable routine, and return a 115 pointer to it. 116 The warn_unused_result attribute serves to aid for early users who may be 117 surprised by an API change. Early versions of this function used to return 118 void. */ 119 struct jitter_executable_routine* 120 jitter_make_executable_routine (struct jitter_mutable_routine *p) 121 __attribute__ ((nonnull (1), returns_nonnull)); 122 123 /* Destroy the pointed executable routine, freeing its resources. If its 124 original non-executable routine still exists -- in case it has been destroyed 125 already its destruction function has updated a field in the executable 126 routine, and this function will not free the non-executable routine twice. 127 After this function is called it is no longer possible to run any code 128 belonging to the executable routine, even if execution was already in 129 progress or if the function is called from a VM instruction. 130 131 When the user calls this function the reference count of the routine must be 132 exactly one, otherwise this function fails fatally. About destruction by 133 jitter_unpin_executable_routine and the difference in behaviour compared to a 134 direct use of this function, see the comment about the reference_count struct 135 field above. */ 136 void 137 jitter_destroy_executable_routine (struct jitter_executable_routine *p) 138 __attribute__ ((nonnull (1))); 139 140 /* Increment the reference_count field of the pointed executable routine, 141 notifying the system that one more reference handled by the user has been 142 added. */ 143 void 144 jitter_pin_executable_routine (struct jitter_executable_routine *er); 145 146 /* Decrement the reference_count field of the pointed executable routine, 147 notifying the system that one reference to the executable routine has been 148 destroyed. 149 If the count reaches zero immediately destroy the executable routine and, if 150 still existing, its mutable companion. Notice that the behavior of 151 jitter_destroy_executable_routine is different, in that 152 jitter_destroy_executable_routine does not destroy the mutable companion. */ 153 void 154 jitter_unpin_executable_routine (struct jitter_executable_routine *er); 155 156 157 158 159 /* Program points. 160 * ************************************************************************** */ 161 162 /* The type of a program point at run time in an executable routine. This is 163 the type of object than can be passed to JITTER_BRANCH , and its actual 164 definition depends on the dispatching model. Notice that however, in every 165 case, a program point is a pointer-to-constant type and therefore fits in a 166 word. */ 167 #ifdef JITTER_DISPATCH_NO_THREADING 168 /* With no-threading dispatch a program point is the address of a machine 169 instruction -- from C, it's what a goto * statement accepts. I don't 170 need to worry about non-GCC compilers, since no-threading relies on GCC 171 extensions. */ 172 typedef const void * 173 jitter_program_point; 174 #else 175 /* On every other dispatching model a program point is a pointer to a word 176 in the executable routine -- in the case of switch dispatching that word 177 will contain a specialized opcode, with threading it will contain the 178 address of a machine instruction (see the case above) followed by the 179 VM instruction arguments. */ 180 typedef const union jitter_word * 181 jitter_program_point; 182 #endif // #ifdef JITTER_DISPATCH_NO_THREADING 183 184 /* Expand to an expression evaluating to the program point of the first 185 instruction in the pointed executable routine, as some object which is 186 correct to pass to JITTER_BRANCH. The expression type will be 187 jitter_program_point. 188 189 This macro is usable from within VM instructions, which might for example 190 perform a jump to the beginning of a different VM routine. The expansion of 191 this macro is guaranteed not to contain function calls, and is safe to use 192 without extra C function wrappers. */ 193 #ifdef JITTER_DISPATCH_NO_THREADING 194 /* In this case the executable routine contains a separate pointer to the 195 beginning of the executable region for the native routine. Of course 196 the first instruction is at the beginning of the region. */ 197 # define JITTER_EXECUTABLE_ROUTINE_BEGINNING(_jitter_executable_routine_ptr) \ 198 ((_jitter_executable_routine_ptr)->native_code) 199 #else 200 /* With switch dispatching or threading the first program point is a pointer 201 to the beginning of the specialized routine array. */ 202 # define JITTER_EXECUTABLE_ROUTINE_BEGINNING(_jitter_executable_routine_ptr) \ 203 ((jitter_program_point) \ 204 ((_jitter_executable_routine_ptr)->specialized_program)) 205 #endif // ifdef JITTER_DISPATCH_NO_THREADING 206 207 208 209 210 /* Internal declarations. 211 * ************************************************************************** */ 212 213 /* What follows is not for the user. */ 214 215 /* Some specialized instruction opcodes whose values must always be valid, 216 independently from the VM. This is checked with assertions at the first 217 run of the specializer -- see templates/vm1.c . */ 218 enum jitter_specialized_instruction_opcode 219 { 220 jitter_specialized_instruction_opcode_INVALID = 0, 221 jitter_specialized_instruction_opcode_BEGINBASICBLOCK = 1, 222 jitter_specialized_instruction_opcode_EXITVM = 2, 223 jitter_specialized_instruction_opcode_DATALOCATIONS = 3, 224 jitter_specialized_instruction_opcode_NOP = 4, 225 jitter_specialized_instruction_opcode_UNREACHABLE0 = 5, 226 jitter_specialized_instruction_opcode_UNREACHABLE1 = 6, 227 jitter_specialized_instruction_opcode_UNREACHABLE2 = 7, 228 }; 229 230 /* Add an opcode to the specialized program which is being built. This is an 231 auxiliary function used by vmprefix_specialize_instruction . The opcode type 232 should actually be the VM-dependent enum 233 vmprefix_specialized_instruction_opcode , but it's safe to use a sufficiently 234 wide unsigned type so that this code is VM-independent. */ 235 void 236 jitter_add_specialized_instruction_opcode 237 (struct jitter_mutable_routine *p, 238 /* This is actually an enum vmprefix_specialized_instruction_opcode , but 239 the type is VM-dependent. */ 240 jitter_uint opcode); 241 242 /* Add a fixnum literal to the specialized program which is being built. This 243 is an auxiliary function used by vmprefix_specialize_instruction . */ 244 void 245 jitter_add_specialized_instruction_literal (struct jitter_mutable_routine *p, 246 jitter_uint literal); 247 248 /* Add a label literal (as an instruction index) to the specialized program 249 which is being built. This is an auxiliary function used by 250 vmprefix_specialize_instruction . */ 251 void 252 jitter_add_specialized_instruction_label_index (struct jitter_mutable_routine *p, 253 jitter_label_as_index 254 unspecialized_instruction_index); 255 256 #endif // #ifndef JITTER_SPECIALIZE_H_ 257