Line data Source code
1 : /* src/vm/jit/verify/typeinfo.hpp - type system used by the type checker
2 :
3 : Copyright (C) 1996-2014
4 : CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 :
6 : This file is part of CACAO.
7 :
8 : This program is free software; you can redistribute it and/or
9 : modify it under the terms of the GNU General Public License as
10 : published by the Free Software Foundation; either version 2, or (at
11 : your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful, but
14 : WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 : General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program; if not, write to the Free Software
20 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 : 02110-1301, USA.
22 :
23 : */
24 :
25 : #ifndef _TYPEINFO_H
26 : #define _TYPEINFO_H
27 :
28 : #include "config.h"
29 : #include "toolbox/assert.hpp"
30 : #include "vm/array.hpp"
31 : #include "vm/global.hpp"
32 : #include "vm/globals.hpp"
33 : #include "vm/references.hpp"
34 : #include "vm/types.hpp"
35 :
36 : struct instruction;
37 : struct varinfo;
38 : struct typeinfo_t;
39 : struct typeinfo_mergedlist_t;
40 : struct typedescriptor_t;
41 :
42 : /* configuration **************************************************************/
43 :
44 : /*
45 : * TYPECHECK_STATISTICS activates gathering statistical information.
46 : * TYPEINFO_DEBUG activates debug checks and debug helpers in typeinfo.cpp
47 : * TYPECHECK_DEBUG activates debug checks in typecheck.c
48 : * TYPEINFO_DEBUG_TEST activates the typeinfo test at startup.
49 : * TYPECHECK_VERBOSE_IMPORTANT activates important debug messages
50 : * TYPECHECK_VERBOSE activates all debug messages
51 : * TYPEINFO_VERBOSE activates debug prints in typeinfo.c
52 : */
53 : #ifdef ENABLE_VERIFIER
54 : #ifndef NDEBUG
55 : /*#define TYPECHECK_STATISTICS*/
56 : #define TYPEINFO_DEBUG
57 : /*#define TYPEINFO_VERBOSE*/
58 : #define TYPECHECK_DEBUG
59 : /*#define TYPEINFO_DEBUG_TEST*/
60 : /*#define TYPECHECK_VERBOSE*/
61 : /*#define TYPECHECK_VERBOSE_IMPORTANT*/
62 : #if defined(TYPECHECK_VERBOSE) || defined(TYPECHECK_VERBOSE_IMPORTANT)
63 : #define TYPECHECK_VERBOSE_OPT
64 : #endif
65 : #endif
66 : #endif
67 :
68 : #ifdef TYPECHECK_VERBOSE_OPT
69 : extern bool opt_typecheckverbose;
70 : #endif
71 :
72 : /* types **********************************************************************/
73 :
74 : /* typecheck_result - return type for boolean and tristate functions */
75 : /* which may also throw exceptions (typecheck_FAIL). */
76 :
77 : /* NOTE: Use the enum values, not the uppercase #define macros! */
78 : #define TYPECHECK_MAYBE 0x02
79 : #define TYPECHECK_FAIL 0x04
80 :
81 : enum typecheck_result {
82 : typecheck_FALSE = false,
83 : typecheck_TRUE = true,
84 : typecheck_MAYBE = TYPECHECK_MAYBE,
85 : typecheck_FAIL = TYPECHECK_FAIL
86 : };
87 :
88 : /* check that typecheck_MAYBE is not ambiguous */
89 : #if TYPECHECK_MAYBE == true
90 : #error "`typecheck_MAYBE` must not be the same as `true`"
91 : #endif
92 : #if TYPECHECK_MAYBE == false
93 : #error "`typecheck_MAYBE` must not be the same as `false`"
94 : #endif
95 :
96 : /* check that typecheck_FAIL is not ambiguous */
97 : #if (true & TYPECHECK_FAIL) != 0
98 : #error "`true` must not have bit 0x02 set (conflicts with typecheck_FAIL)"
99 : #endif
100 :
101 : /* data structures for the type system ****************************************/
102 :
103 : /* The typeinfo structure stores detailed information on address types.
104 : * (stack elements, variables, etc. with type == TYPE_ADR.)
105 : *
106 : * There are two kinds of address types which can be distinguished by
107 : * the value of the typeclass field:
108 : *
109 : * 1) typeclass == NULL: returnAddress type
110 : * use typeinfo::is_primitive() to test for this
111 : *
112 : * 2) typeclass != NULL: reference type
113 : * use typeinfo::is_reference() to test for this
114 : *
115 : * Note: For non-address types either there is no typeinfo allocated
116 : * or the fields of the typeinfo struct contain undefined values!
117 : * DO NOT access the typeinfo for non-address types!
118 : *
119 : * CAUTION: The typeinfo structure should be considered opaque outside of
120 : * typeinfo.[ch]. Please use the macros and functions defined here to
121 : * access typeinfo structures!
122 : */
123 :
124 : /* At all times *exactly one* of the following conditions is true for
125 : * a particular typeinfo struct:
126 : *
127 : * A) typeclass == NULL
128 : *
129 : * This is a returnAddress type.
130 : *
131 : * Use typeinfo::is_primitive() to check for this.
132 : * Use typeinfo::returnaddress() to access the pointer in elementclass.
133 : * Don't access other fields of the struct.
134 : *
135 : * B) typeclass == pseudo_class_Null
136 : *
137 : * This is the null-reference type.
138 : * Use typeinfo::is_nulltype() to check for this.
139 : * Don't access other fields of the struct.
140 : *
141 : * C) typeclass == pseudo_class_New
142 : *
143 : * This is an 'uninitialized object' type. elementclass can be
144 : * cast to instruction* and points to the NEW instruction
145 : * responsible for creating this type.
146 : *
147 : * Use typeinfo::newobject_instruction to access the pointer in
148 : * elementclass.
149 : * Don't access other fields of the struct.
150 : *
151 : * D) typeclass == pseudo_class_Arraystub
152 : *
153 : * This type is used to represent the result of merging array types
154 : * with incompatible component types. An arraystub allows no access
155 : * to its components (since their type is undefined), but it allows
156 : * operations which act directly on an arbitrary array type (such as
157 : * requesting the array size).
158 : *
159 : * NOTE: An array stub does *not* count as an array. It has dimension
160 : * zero.
161 : *
162 : * Otherwise like a normal class reference type.
163 : * Don't access other fields of the struct.
164 : *
165 : * E) typeclass is an array class
166 : *
167 : * An array reference.
168 : * elementclass...typeclass of the element type
169 : * dimension......dimension of the array (>=1)
170 : * elementtype....element type (ARRAYTYPE_...)
171 : * merged.........mergedlist of the element type
172 : *
173 : * Use typeinfo:is_array to check for this case.
174 : *
175 : * The elementclass may be one of the following:
176 : * 1) pseudo_class_Arraystub
177 : * 2) an unresolved type
178 : * 3) a loaded interface
179 : * 4) a loaded (non-pseudo-,non-array-)class != (BOOTSTRAP)java.lang.Object
180 : * Note: `merged` may be used
181 : * 5) (BOOTSTRAP)java.lang.Object
182 : * Note: `merged` may be used
183 : *
184 : * For the semantics of the merged field in cases 4) and 5) consult the
185 : * corresponding descriptions with `elementclass` replaced by `typeclass`.
186 : *
187 : * F) typeclass is an unresolved type (a symbolic class/interface reference)
188 : *
189 : * The type has not been resolved yet. (Meaning it corresponds to an
190 : * unloaded class or interface).
191 : * Don't access other fields of the struct.
192 : *
193 : * G) typeclass is a loaded interface
194 : *
195 : * An interface reference type.
196 : * Don't access other fields of the struct.
197 : *
198 : * H) typeclass is a loaded (non-pseudo-,non-array-)class != (BOOTSTRAP)java.lang.Object
199 : *
200 : * A loaded class type.
201 : * All classref_or_classinfos in u.merged.list (if any) are
202 : * loaded subclasses of typeclass (no interfaces, array classes, or
203 : * unresolved types).
204 : * Don't access other fields of the struct.
205 : *
206 : * I) typeclass is (BOOTSTRAP)java.lang.Object
207 : *
208 : * The most general kind of reference type.
209 : * In this case u.merged.count and u.merged.list
210 : * are valid and may be non-zero.
211 : * The classref_or_classinfos in u.merged.list (if any) may be
212 : * classes, interfaces, pseudo classes or unresolved types.
213 : * Don't access other fields of the struct.
214 : */
215 :
216 : /* The following algorithm is used to determine if the type described
217 : * by this typeinfo struct supports the interface X: * XXX add MAYBE *
218 : *
219 : * 1) If typeclass is X or a subinterface of X the answer is "yes".
220 : * 2) If typeclass is a (pseudo) class implementing X the answer is "yes".
221 : * 3) If typeclass is not an array and u.merged.count>0
222 : * and all classes/interfaces in u.merged.list implement X
223 : * the answer is "yes".
224 : * 4) If none of the above is true the answer is "no".
225 : */
226 :
227 : /*
228 : * CAUTION: The typeinfo structure should be considered opaque outside of
229 : * typeinfo.[ch]. Please use the macros and functions defined here to
230 : * access typeinfo structures!
231 : */
232 :
233 : void typeinfo_init_classinfo(typeinfo_t *info,classinfo *c);
234 :
235 : struct typeinfo_t {
236 : classref_or_classinfo typeclass;
237 : classref_or_classinfo elementclass; // valid if dimension>0 (various uses!)
238 : typeinfo_mergedlist_t *merged;
239 : u1 dimension;
240 : ArrayType elementtype; // valid if dimension>0
241 :
242 2882340 : bool is_primitive() const { return typeclass.any == NULL; }
243 900630 : bool is_reference() const { return typeclass.any != NULL; }
244 :
245 844196 : bool is_nulltype() const { return typeclass.cls == pseudo_class_Null; }
246 2520103 : bool is_newobject() const { return typeclass.cls == pseudo_class_New; }
247 :
248 0 : void *returnaddress() const {
249 : EXPENSIVE_ASSERT(is_primitive());
250 :
251 0 : return elementclass.any;
252 : }
253 :
254 225166 : instruction *newobject_instruction() const {
255 : EXPENSIVE_ASSERT(is_newobject());
256 :
257 225166 : return (instruction*) elementclass.any;
258 : }
259 :
260 282723 : bool is_array() const { return is_reference() && dimension != 0; }
261 521032 : bool is_simple_array() const { return dimension == 1; }
262 :
263 521032 : bool is_primitive_array(ArrayType at) const {
264 521032 : return is_simple_array() && elementtype == at;
265 : }
266 85850 : bool is_array_of_refs() const {
267 85850 : return is_array() && (elementclass.any != NULL || dimension >= 2);
268 : }
269 :
270 : // queries allowing the null type
271 :
272 9830 : bool maybe_array() const {
273 9830 : return is_array() || is_nulltype();
274 : }
275 :
276 521032 : bool maybe_primitive_array(ArrayType at) const {
277 521032 : return is_primitive_array(at) || is_nulltype();
278 : }
279 :
280 85850 : bool maybe_array_of_refs() const {
281 85850 : return is_array_of_refs() || is_nulltype();
282 : }
283 :
284 : // Check if `this' type is assignable to a given destination type.
285 : typecheck_result is_assignable_to(typeinfo_t *dest) const;
286 : typecheck_result is_assignable_to_class(classref_or_classinfo dest) const;
287 :
288 : // initializing typeinfo structures
289 :
290 136016 : void init_primitive() {
291 136016 : typeclass.any = NULL;
292 136016 : elementclass.any = NULL;
293 136016 : merged = NULL;
294 136016 : dimension = 0;
295 136016 : elementtype = ARRAYTYPE_INT;
296 136016 : }
297 :
298 18 : void init_returnaddress(void *adr) {
299 18 : typeclass.any = NULL;
300 18 : elementclass.any = adr;
301 18 : merged = NULL;
302 18 : dimension = 0;
303 18 : elementtype = ARRAYTYPE_INT;
304 18 : }
305 :
306 16910 : void init_non_array_classinfo(classinfo *cls) {
307 16910 : typeclass.cls = cls;
308 16910 : elementclass.any = NULL;
309 16910 : merged = NULL;
310 16910 : dimension = 0;
311 16910 : elementtype = ARRAYTYPE_INT;
312 16910 : }
313 :
314 : /// Initialize object type java.lang.Class
315 64184 : void init_java_lang_class(classref_or_classinfo cls) {
316 64184 : typeclass.cls = class_java_lang_Class;
317 64184 : elementclass = cls;
318 64184 : merged = NULL;
319 64184 : dimension = 0;
320 64184 : elementtype = ARRAYTYPE_INT;
321 64184 : }
322 :
323 : /// Initialize object type
324 : void init_class(classinfo *c);
325 : bool init_class(classref_or_classinfo c);
326 :
327 305647 : bool init_class(constant_classref *c) {
328 305647 : return init_class(to_classref_or_classinfo(c));
329 : }
330 :
331 : bool init_component(const typeinfo_t& srcarray);
332 :
333 : bool init_from_typedesc(const typedesc *desc, u1 *type);
334 :
335 16910 : void init_nulltype() {
336 16910 : init_non_array_classinfo(pseudo_class_Null);
337 16910 : }
338 :
339 78467 : void init_newobject(instruction *instr) {
340 78467 : typeclass.cls = pseudo_class_New;
341 78467 : elementclass.any = instr;
342 78467 : merged = NULL;
343 78467 : dimension = 0;
344 78467 : elementtype = ARRAYTYPE_INT;
345 78467 : }
346 :
347 5937 : void init_primitive_array(ArrayType arraytype) {
348 5937 : init_class(primitivetype_table[arraytype].arrayclass);
349 5937 : }
350 :
351 : // copying types (destinition is not checked or freed)
352 :
353 : /***
354 : * makes a deep copy, the merged list (if any) is duplicated
355 : * into a newly allocated array.
356 : */
357 15380 : static void clone(const typeinfo_t& src, typeinfo_t& dst) {
358 15380 : dst = src;
359 :
360 15380 : if (dst.merged)
361 2268 : clone_merged(src, dst);
362 15380 : }
363 :
364 : /// functions for merging types
365 :
366 : typecheck_result merge(methodinfo *m, const typeinfo_t* t);
367 : private:
368 : static void clone_merged(const typeinfo_t& src, typeinfo_t& dst);
369 : };
370 :
371 :
372 : struct typeinfo_mergedlist_t {
373 : s4 count;
374 : classref_or_classinfo list[1]; /* variable length! */
375 : };
376 :
377 : /* a type descriptor stores a basic type and the typeinfo */
378 : /* this is used for storing the type of a local variable, and for */
379 : /* storing types in the signature of a method */
380 :
381 : struct typedescriptor_t {
382 : typeinfo_t typeinfo; /* valid if type == TYPE_ADR */
383 : Type type; /* basic type (TYPE_INT, ...) */
384 :
385 0 : bool is_returnaddress() const { return type == TYPE_RET && typeinfo.is_primitive(); }
386 0 : bool is_reference() const { return type == TYPE_ADR && typeinfo.is_reference(); }
387 : };
388 :
389 :
390 : /****************************************************************************/
391 : /* MACROS */
392 : /****************************************************************************/
393 :
394 : /* NOTE: The TYPEINFO macros take typeinfo *structs*, not pointers as
395 : * arguments. You have to dereference any pointers.
396 : */
397 :
398 : /* typevectors **************************************************************/
399 :
400 : #define TYPEVECTOR_SIZE(size) \
401 : ((size) * sizeof(varinfo))
402 :
403 : #define DNEW_TYPEVECTOR(size) \
404 : ((varinfo *) DumpMemory::allocate(TYPEVECTOR_SIZE(size)))
405 :
406 : #define DMNEW_TYPEVECTOR(num,size) \
407 : ((varinfo *) DumpMemory::allocate((num) * TYPEVECTOR_SIZE(size)))
408 :
409 : #define MGET_TYPEVECTOR(array,index,size) \
410 : ((varinfo*) (((u1*)(array)) + TYPEVECTOR_SIZE(size) * (index)))
411 :
412 :
413 : /****************************************************************************/
414 : /* FUNCTIONS */
415 : /****************************************************************************/
416 :
417 : /* typevector functions *****************************************************/
418 :
419 : /* element read-only access */
420 : bool typevector_checktype(varinfo *set,int index,int type);
421 : bool typevector_checkreference(varinfo *set,int index);
422 : bool typevector_checkretaddr(varinfo *set,int index);
423 :
424 : /* element write access */
425 : void typevector_store(varinfo *set,int index, Type type,typeinfo_t *info);
426 : void typevector_store_retaddr(varinfo *set,int index,typeinfo_t *info);
427 : bool typevector_init_object(varinfo *set,void *ins,classref_or_classinfo initclass,int size);
428 :
429 : /* vector functions */
430 : varinfo *typevector_copy(varinfo *src,int size);
431 : void typevector_copy_inplace(varinfo *src,varinfo *dst,int size);
432 : typecheck_result typevector_merge(methodinfo *m,varinfo *dst,varinfo *y,int size);
433 :
434 : /* initialization functions *************************************************/
435 :
436 : /* RETURN VALUE (bool):
437 : * true.............ok,
438 : * false............an exception has been thrown.
439 : *
440 : * RETURN VALUE (int):
441 : * >= 0.............ok,
442 : * -1...............an exception has been thrown.
443 : */
444 : int typedescriptors_init_from_methoddesc(typedescriptor_t *td,
445 : methoddesc *desc,
446 : int buflen,bool twoword,int startindex,
447 : typedescriptor_t *returntype);
448 : bool typeinfo_init_varinfos_from_methoddesc(varinfo *vars,
449 : methoddesc *desc,
450 : int buflen, int startindex,
451 : s4 *map,
452 : typedescriptor_t *returntype);
453 :
454 : /* debugging helpers ********************************************************/
455 :
456 : #ifdef TYPEINFO_DEBUG
457 :
458 : #include <stdio.h>
459 :
460 : void typeinfo_test();
461 : void typeinfo_print_class(FILE *file, classref_or_classinfo c);
462 : void typeinfo_print(FILE *file, const typeinfo_t *info, int indent);
463 : void typeinfo_print_short(FILE *file, const typeinfo_t *info);
464 : void typeinfo_print_type(FILE *file, int type, const typeinfo_t *info);
465 : void typedescriptor_print(FILE *file, typedescriptor_t *td);
466 : void typevector_print(FILE *file, varinfo *vec, int size);
467 :
468 : #endif /* TYPEINFO_DEBUG */
469 :
470 : #endif /* _TYPEINFO_H */
471 :
472 :
473 : /*
474 : * These are local overrides for various environment variables in Emacs.
475 : * Please do not remove this and leave it at the end of the file, where
476 : * Emacs will automagically detect them.
477 : * ---------------------------------------------------------------------
478 : * Local variables:
479 : * mode: c++
480 : * indent-tabs-mode: t
481 : * c-basic-offset: 4
482 : * tab-width: 4
483 : * End:
484 : */
|