1 /* Jitter: VM-specific configuration and internal implementation header.
2 
3    Copyright (C) 2017, 2018, 2019 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_VM_H_
23 #define JITTER_VM_H_
24 
25 #include <stdio.h>
26 
27 #include <jitter/jitter.h>
28 #include <jitter/jitter-mutable-routine.h>
29 #include <jitter/jitter-patch-in.h>
30 #include <jitter/jitter-list.h>
31 
32 
33 
34 
35 /* VM-specific attributes.
36  * ************************************************************************** */
37 
38 /* The kind of profiling instrumentation enabled in a VM.  This is selected with
39    CPP macros when compiling vm1 and vm2.
40 
41    Notice that the enum value can be used as a bit mask, with
42    jitter_vm_instrumentation_count and jitter_vm_instrumentation_sample being
43    two independent features that can be enabled or disabled, each contributing
44    to the enum jitter_vm_instrumentation value as operands of a bitwise or
45    operation. */
46 enum jitter_vm_instrumentation
47   {
48     /* No instrumentation, as suitable for production. */
49     jitter_vm_instrumentation_none
50       = 0,
51 
52     /* Counting instrumentation.  This permits to count how many time each
53        specialised instruction is executed, exactly.
54        This mode is unsuitable for production as the instrumentation overhead
55        is severe.  For every VM instruction:
56        - load;
57        - 64-bit load (often with an offset larger than 16 bits);
58        - 64-bit increment;
59        - 64-bit store (often with an offset larger than 16 bits).
60        This is also heavy on l1d, since the 64-bit memory location accessed
61        depends on the specialised opcode, and many different location can be
62        touched. */
63     jitter_vm_instrumentation_count
64       = 1,
65 
66     /* Sampling instrumentation.  This permits to count how much time is spent
67        executing each specialised instruction, subject to sampling errors.
68        The instrumentation overhead is less extreme in this case.  For every
69        VM instruction:
70        - store of a 16-bit constant (zero-extended or sign-extended to word
71          size) depending on the instruction;
72        and then the overhead of handling a periodic signal.
73        The address being written to is always the same. */
74     jitter_vm_instrumentation_sample
75       = 2,
76 
77     /* Enable both counting and sampling.  The overhead will be equal to the sum
78        of the two overheads above, again making this mode is again unsuitable
79        for production VMs. */
80     jitter_vm_instrumentation_count_and_sample
81       = jitter_vm_instrumentation_count | jitter_vm_instrumentation_sample
82   };
83 
84 /* Return a human-readable description of the given instrumentation.  The
85    returned string points to global constant memory, and the user does not
86    need to free it. */
87 const char *
88 jitter_vm_instrumentation_to_string (enum jitter_vm_instrumentation i);
89 
90 /* A struct containing the configuration-specific parameters of a VM.  This
91    struct exists in only one constant instance per VM, and does not depend on
92    initialisation functions.  It is convenient to be used, for example, in
93    handling the command-line option --version . */
94 struct jitter_vm_configuration
95 {
96   /* Identifier prefixes for the generated C code. */
97   char *lower_case_prefix, *upper_case_prefix;
98 
99   /* How many fast registers per class this VM can have, as a maximum.  -1 means
100      that there is no limit. */
101   int max_fast_register_no_per_class;
102 
103   /* How many nonresidual literals we support, as a maximum; -1 means that there
104      is no limit. */
105   int max_nonresidual_literal_no;
106 
107   /* A textual description of the dispatching technique. */
108   char *dispatch_human_readable;
109 
110   /* The kind of profiling instrumentation for this VM. */
111   enum jitter_vm_instrumentation instrumentation;
112 };
113 
114 /* Print the current VM configuration, as set by jitterc and CPP macros, to the
115    given stream in a human-readable format. */
116 void
117 jitter_print_vm_configuration (FILE *f,
118                                const struct jitter_vm_configuration *c);
119 
120 
121 
122 
123 /* VM internal implementation.
124  * ************************************************************************** */
125 
126 /* Everything from this point on is subject to change and not meant for the
127    user. */
128 
129 /* A struct defining the VM-specific attributes of a VM.  Each VM has its own
130    unique instance of this, shared by every routine for the same VM and
131    initialized by vmprefix_initialize in template code.
132    This structure is used internally, and the user does not need to see it. */
133 struct jitter_vm
134 {
135   /* Configuration-specific data for this VM. */
136   const struct jitter_vm_configuration *configuration;
137 
138 /* Threads or pointers to native code blocks of course don't exist with
139    switch-dispatching. */
140 #ifndef JITTER_DISPATCH_SWITCH
141   /* True iff threads appear to be valid: of non-negative size, sequential,
142      non-overlapping. */
143   bool threads_validated;
144 
145   // FIXME: add a comment per field.
146   jitter_thread *threads;
147   long *thread_sizes;
148 
149   /* The address of the symbol defined in the data location subsection as
150      a const char * global.  See jitter-data-locations.h . */
151   const char *data_locations;
152 #endif // #ifndef JITTER_DISPATCH_SWITCH
153 
154   const size_t *specialized_instruction_residual_arities;
155   const unsigned long *specialized_instruction_label_bitmasks;
156 
157   /* This is NULL when using a dispatching model not needing the bitmask. */
158   const unsigned long *specialized_instruction_fast_label_bitmasks;
159 
160 #ifdef JITTER_HAVE_PATCH_IN
161   const struct jitter_patch_in_descriptor *patch_in_descriptors;
162   size_t patch_in_descriptor_no;
163   /* A patch-in table as defined in jitter/jitter-patch-in.h . */
164   struct patch_in_table_entry *patch_in_table;
165 #endif // #ifdef JITTER_HAVE_PATCH_IN
166 
167   const bool *specialized_instruction_relocatables;
168   const bool *specialized_instruction_callers;
169   const bool *specialized_instruction_callees;
170   const char * const *specialized_instruction_names;
171   size_t specialized_instruction_no;
172 
173   struct jitter_hash_table *meta_instruction_string_hash;
174 
175   struct jitter_meta_instruction *meta_instructions;
176   size_t meta_instruction_no;
177 
178   /* An array whose indices are specialised instruction opcodes, and whose
179      elements are the corresponding unspecialised instructions opcodes -- or -1
180      when there is no mapping mapping having */
181   const int *specialized_instruction_to_unspecialized_instruction;
182 
183   /* Specific meta-instruction pointers for implicit instructions.
184      VM-independent routine specialization relies on those, so they have to be
185      accessible to the Jitter library, out of generated code*/
186   const struct jitter_meta_instruction *exitvm_meta_instruction;
187   const struct jitter_meta_instruction *unreachable_meta_instruction;
188 
189   /* The longest unspecialized/meta instruction name length, not mangled,
190      without counting the final '\0' character.  Special specialized
191      instruction, having no unspecialized counterparts, are ignored here. */
192   size_t max_meta_instruction_name_length;
193 
194   /* A function returning a pointer to a constant register class descriptor
195      given the register class character, or NULL if the character is not
196      associated to any register class. */
197   const struct jitter_register_class *
198   (* register_class_character_to_register_class) (char c);
199 
200   /* Translate one or more unspecialized instructions starting from *ins into
201      p->specialized_program by calling the appropriate
202      vmprefix_add_specialized_instruction_* functions for the opcode and every
203      argument, returning the number of unspecialized instructions covered by the
204      one new specialized instruction which is being added.  The result is always
205      1 or more -- more than 1 when a superinstruction is being recognized.  The
206      actual function is machine-generated. */
207   /* FIXME: the comment above has been obsolete for a long time (in the end I
208      decided not to have superinstructions), and the API can be simplified.
209      The result should be void, not int. */
210   int (*specialize_instruction) (struct jitter_mutable_routine *p,
211                                  const struct jitter_instruction *ins);
212 
213   /* Rewrite an instruction.  This points to the vmprefix_rewrite function declared
214      in templates/vm.h and implemented in Jitter-generated code. */
215   void (*rewrite) (struct jitter_mutable_routine *p);
216 
217   /* A linked list of all the existing states for this VM. */
218   struct jitter_list_header states;
219 };
220 
221 
222 #endif // #ifndef JITTER_VM_H_
223