Line data Source code
1 : /* src/vm/class.cpp - class related functions
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 : #include "vm/class.hpp"
26 :
27 : #include "config.h"
28 :
29 : #include <assert.h>
30 : #include <inttypes.h> // for PRId64
31 : #include <stdio.h>
32 : #include <stdlib.h>
33 : #include <string.h>
34 :
35 : #include "arch.hpp"
36 :
37 : #include "mm/memory.hpp"
38 :
39 : #include "native/llni.hpp"
40 :
41 : #include "threads/lock.hpp"
42 : #include "threads/lockword.hpp" // for Lockword
43 : #include "threads/mutex.hpp"
44 : #include "threads/thread.hpp" // for thread_get_current, etc
45 :
46 : #include "toolbox/OStream.hpp" // for OStream
47 : #include "toolbox/hashtable.hpp" // for hashtable
48 : #include "toolbox/logging.hpp"
49 :
50 : #include "vm/annotation.hpp"
51 : #include "vm/array.hpp"
52 : #include "vm/class.hpp"
53 : #include "vm/classcache.hpp"
54 : #include "vm/exceptions.hpp"
55 : #include "vm/field.hpp" // for fieldinfo, etc
56 : #include "vm/global.hpp"
57 : #include "vm/globals.hpp"
58 : #include "vm/javaobjects.hpp"
59 : #include "vm/linker.hpp"
60 : #include "vm/loader.hpp"
61 : #include "vm/method.hpp" // for methodinfo, etc
62 : #include "vm/options.hpp"
63 : #include "vm/primitive.hpp" // for Primitive
64 : #include "vm/resolve.hpp"
65 : #include "vm/statistics.hpp"
66 : #include "vm/string.hpp" // for JavaString
67 : #include "vm/suck.hpp"
68 : #include "vm/string.hpp"
69 : #include "vm/types.hpp"
70 : #include "vm/utf8.hpp"
71 :
72 : #include "vm/jit/builtin.hpp"
73 :
74 : STAT_DECLARE_GROUP(info_struct_stat)
75 : STAT_DECLARE_VAR(int,size_classinfo,0)
76 :
77 : using namespace cacao;
78 :
79 : /**
80 : * Returns the classname of the class, where slashes ('/') are
81 : * replaced by dots ('.').
82 : *
83 : * @param c class to get name of
84 : * @return classname
85 : */
86 4118 : extern java_handle_t* class_get_classname(classinfo* c)
87 : {
88 4118 : return JavaString::from_utf8_slash_to_dot(c->name);
89 : }
90 :
91 :
92 : /* class_set_packagename *******************************************************
93 :
94 : Derive the package name from the class name and store it in the
95 : struct.
96 :
97 : For classes in the unnamed package, the package name is set to
98 : NULL.
99 :
100 : *******************************************************************************/
101 :
102 43459 : void class_set_packagename(classinfo *c)
103 : {
104 43459 : Utf8String name = c->name;
105 :
106 43459 : const char *p = name.end() - 1;
107 43459 : const char *start = name.begin();
108 :
109 43459 : if (name[0] == '[') {
110 : /* Set packagename of arrays to the element's package. */
111 :
112 4944 : for (; *start == '['; start++);
113 :
114 : /* Skip the 'L' in arrays of references. */
115 :
116 4944 : if (*start == 'L')
117 3092 : start++;
118 : }
119 :
120 : /* Search for last '/'. */
121 :
122 43459 : for (; (p > start) && (*p != '/'); --p);
123 :
124 : /* If we found a '/' we set the package name. Otherwise we set the
125 : packagename to NULL. */
126 :
127 43459 : if (p > start)
128 38831 : c->packagename = Utf8String::from_utf8_slash_to_dot(start, p - start);
129 : else
130 4628 : c->packagename = NULL;
131 43459 : }
132 :
133 :
134 : /* class_create_classinfo ******************************************************
135 :
136 : Create a new classinfo struct. The class name is set to the given utf string,
137 : most other fields are initialized to zero.
138 :
139 : Note: classname may be NULL. In this case a not-yet-named classinfo is
140 : created. The name must be filled in later and class_set_packagename
141 : must be called after that.
142 :
143 : *******************************************************************************/
144 :
145 43459 : classinfo *class_create_classinfo(Utf8String classname)
146 : {
147 : classinfo *c;
148 :
149 : STATISTICS(size_classinfo += sizeof(classinfo));
150 :
151 : /* we use a safe name for temporarily unnamed classes */
152 :
153 43459 : if (classname == NULL)
154 2 : classname = utf8::not_named_yet;
155 :
156 : #if !defined(NDEBUG)
157 43459 : if (initverbose)
158 0 : log_message_utf("Creating class: ", classname);
159 : #endif
160 :
161 : #if !defined(ENABLE_GC_BOEHM)
162 : c = (classinfo *) heap_alloc_uncollectable(sizeof(classinfo));
163 : /*c = NEW(classinfo);
164 : MZERO(c, classinfo, 1);*/
165 : #else
166 43459 : c = GCNEW_UNCOLLECTABLE(classinfo, 1);
167 : /* GCNEW_UNCOLLECTABLE clears the allocated memory */
168 : #endif
169 :
170 43459 : c->name = classname;
171 :
172 : /* Set the header.vftbl of all loaded classes to the one of
173 : java.lang.Class, so Java code can use a class as object. */
174 :
175 43459 : if (class_java_lang_Class != NULL)
176 37754 : if (class_java_lang_Class->vftbl != NULL)
177 31234 : c->object.header.vftbl = class_java_lang_Class->vftbl;
178 :
179 : #if defined(ENABLE_JAVASE)
180 : /* check if the class is a reference class and flag it */
181 :
182 43459 : if (classname == utf8::java_lang_ref_SoftReference) {
183 0 : c->flags |= ACC_CLASS_REFERENCE_SOFT;
184 : }
185 43459 : else if (classname == utf8::java_lang_ref_WeakReference) {
186 163 : c->flags |= ACC_CLASS_REFERENCE_WEAK;
187 : }
188 43296 : else if (classname == utf8::java_lang_ref_PhantomReference) {
189 0 : c->flags |= ACC_CLASS_REFERENCE_PHANTOM;
190 : }
191 : #endif
192 :
193 43459 : if (classname != utf8::not_named_yet)
194 43457 : class_set_packagename(c);
195 :
196 43459 : Lockword(c->object.header.lockword).init();
197 :
198 43459 : return c;
199 : }
200 :
201 :
202 : /* class_postset_header_vftbl **************************************************
203 :
204 : Set the header.vftbl of all classes created before java.lang.Class
205 : was linked. This is necessary that Java code can use a class as
206 : object.
207 :
208 : *******************************************************************************/
209 :
210 163 : void class_postset_header_vftbl(void)
211 : {
212 : classinfo *c;
213 : u4 slot;
214 : classcache_name_entry *nmen;
215 : classcache_class_entry *clsen;
216 :
217 163 : assert(class_java_lang_Class);
218 :
219 333987 : for (slot = 0; slot < hashtable_classcache.size; slot++) {
220 333824 : nmen = (classcache_name_entry *) hashtable_classcache.ptr[slot];
221 :
222 344582 : for (; nmen; nmen = nmen->hashlink) {
223 : /* iterate over all class entries */
224 :
225 21516 : for (clsen = nmen->classes; clsen; clsen = clsen->next) {
226 10758 : c = clsen->classobj;
227 :
228 : /* now set the the vftbl */
229 :
230 10758 : if (c->object.header.vftbl == NULL)
231 10758 : c->object.header.vftbl = class_java_lang_Class->vftbl;
232 : }
233 : }
234 : }
235 163 : }
236 :
237 : /* class_define ****************************************************************
238 :
239 : Calls the loader and defines a class in the VM.
240 :
241 : *******************************************************************************/
242 :
243 644 : classinfo *class_define(Utf8String name, classloader_t *cl, int32_t length, uint8_t *data, java_handle_t *pd)
244 : {
245 644 : if (name != NULL) {
246 : /* check if this class has already been defined */
247 :
248 642 : classinfo *c = classcache_lookup_defined_or_initiated(cl, name);
249 :
250 642 : if (c != NULL) {
251 0 : exceptions_throw_linkageerror("duplicate class definition: ", c);
252 0 : return NULL;
253 : }
254 : }
255 :
256 : /* create a new classinfo struct */
257 :
258 644 : classinfo *c = class_create_classinfo(name);
259 :
260 : #if defined(ENABLE_STATISTICS)
261 : /* measure time */
262 :
263 : if (opt_getloadingtime)
264 : loadingtime_start();
265 : #endif
266 :
267 : /* preset the defining classloader */
268 :
269 644 : c->classloader = cl;
270 :
271 : /* build a classbuffer with the given data */
272 :
273 644 : ClassBuffer cb(c, data, length);
274 :
275 : /* load the class from this buffer */
276 :
277 644 : classinfo *r = load_class_from_classbuffer(cb);
278 :
279 : #if defined(ENABLE_STATISTICS)
280 : /* measure time */
281 :
282 : if (opt_getloadingtime)
283 : loadingtime_stop();
284 : #endif
285 :
286 644 : if (r == NULL) {
287 : /* If return value is NULL, we had a problem and the class is
288 : not loaded. Now free the allocated memory, otherwise we
289 : could run into a DOS. */
290 :
291 2 : class_free(c);
292 :
293 2 : return NULL;
294 : }
295 :
296 : #if defined(ENABLE_JAVASE)
297 : # if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
298 : /* Store the protection domain. */
299 :
300 : c->protectiondomain = pd;
301 : # endif
302 : #endif
303 :
304 : /* Store the newly defined class in the class cache. This call
305 : also checks whether a class of the same name has already been
306 : defined by the same defining loader, and if so, replaces the
307 : newly created class by the one defined earlier. */
308 :
309 : /* Important: The classinfo given to classcache_store must be
310 : fully prepared because another thread may return
311 : this pointer after the lookup at to top of this
312 : function directly after the class cache lock has
313 : been released. */
314 :
315 642 : c = classcache_store(cl, c, true);
316 :
317 642 : return c;
318 : }
319 :
320 :
321 : /* class_load_attribute_sourcefile *********************************************
322 :
323 : SourceFile_attribute {
324 : u2 attribute_name_index;
325 : u4 attribute_length;
326 : u2 sourcefile_index;
327 : }
328 :
329 : *******************************************************************************/
330 :
331 35765 : static bool class_load_attribute_sourcefile(ClassBuffer& cb)
332 : {
333 : /* get classinfo */
334 :
335 35765 : classinfo *c = cb.get_class();
336 :
337 : /* check buffer size */
338 :
339 35765 : if (!cb.check_size(4 + 2))
340 0 : return false;
341 :
342 : /* check attribute length */
343 :
344 35765 : u4 attribute_length = cb.read_u4();
345 :
346 35765 : if (attribute_length != 2) {
347 0 : exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
348 0 : return false;
349 : }
350 :
351 : /* there can be no more than one SourceFile attribute */
352 :
353 35765 : if (c->sourcefile != NULL) {
354 0 : exceptions_throw_classformaterror(c, "Multiple SourceFile attributes");
355 0 : return false;
356 : }
357 :
358 : /* get sourcefile */
359 :
360 35765 : u2 sourcefile_index = cb.read_u2();
361 35765 : Utf8String sourcefile = (utf*) class_getconstant(c, sourcefile_index, CONSTANT_Utf8);
362 :
363 35765 : if (sourcefile == NULL)
364 0 : return false;
365 :
366 : /* store sourcefile */
367 :
368 35765 : c->sourcefile = sourcefile;
369 :
370 35765 : return true;
371 : }
372 :
373 :
374 : /* class_load_attribute_enclosingmethod ****************************************
375 :
376 : EnclosingMethod_attribute {
377 : u2 attribute_name_index;
378 : u4 attribute_length;
379 : u2 class_index;
380 : u2 method_index;
381 : }
382 :
383 : *******************************************************************************/
384 :
385 : #if defined(ENABLE_JAVASE)
386 1530 : static bool class_load_attribute_enclosingmethod(ClassBuffer& cb) {
387 : classref_or_classinfo cr;
388 :
389 : /* get classinfo */
390 :
391 1530 : classinfo *c = cb.get_class();
392 :
393 : /* check buffer size */
394 :
395 1530 : if (!cb.check_size(4 + 2 + 2))
396 0 : return false;
397 :
398 : /* check attribute length */
399 :
400 1530 : u4 attribute_length = cb.read_u4();
401 :
402 1530 : if (attribute_length != 4) {
403 0 : exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
404 0 : return false;
405 : }
406 :
407 : /* there can be no more than one EnclosingMethod attribute */
408 :
409 1530 : if (c->enclosingmethod != NULL) {
410 0 : exceptions_throw_classformaterror(c, "Multiple EnclosingMethod attributes");
411 0 : return false;
412 : }
413 :
414 : /* get class index */
415 :
416 1530 : u2 class_index = cb.read_u2();
417 1530 : cr.ref = (constant_classref*) innerclass_getconstant(c, class_index, CONSTANT_Class);
418 :
419 : /* get method index */
420 :
421 1530 : u2 method_index = cb.read_u2();
422 1530 : constant_nameandtype *cn = (constant_nameandtype*) innerclass_getconstant(c, method_index, CONSTANT_NameAndType);
423 :
424 : /* store info in classinfo */
425 :
426 1530 : c->enclosingclass.any = cr.any;
427 1530 : c->enclosingmethod = cn;
428 :
429 1530 : return true;
430 : }
431 : #endif /* defined(ENABLE_JAVASE) */
432 :
433 :
434 : /* class_load_attributes *******************************************************
435 :
436 : Read attributes from ClassFile.
437 :
438 : attribute_info {
439 : u2 attribute_name_index;
440 : u4 attribute_length;
441 : u1 info[attribute_length];
442 : }
443 :
444 : InnerClasses_attribute {
445 : u2 attribute_name_index;
446 : u4 attribute_length;
447 : }
448 :
449 : *******************************************************************************/
450 :
451 35788 : bool class_load_attributes(ClassBuffer& cb)
452 : {
453 : classref_or_classinfo outer, inner;
454 :
455 35788 : classinfo *c = cb.get_class();
456 :
457 : /* get attributes count */
458 :
459 35788 : if (!cb.check_size(2))
460 0 : return false;
461 :
462 35788 : uint16_t attributes_count = cb.read_u2();
463 :
464 96304 : for (int i = 0; i < attributes_count; i++) {
465 : /* get attribute name */
466 :
467 60516 : if (!cb.check_size(2))
468 0 : return false;
469 :
470 60516 : uint16_t attribute_name_index = cb.read_u2();
471 60516 : Utf8String attribute_name = (utf*) class_getconstant(c, attribute_name_index, CONSTANT_Utf8);
472 :
473 60516 : if (attribute_name == NULL)
474 0 : return false;
475 :
476 60516 : if (attribute_name == utf8::InnerClasses) {
477 : /* InnerClasses */
478 :
479 12119 : if (c->innerclass != NULL) {
480 0 : exceptions_throw_classformaterror(c, "Multiple InnerClasses attributes");
481 0 : return false;
482 : }
483 :
484 12119 : if (!cb.check_size(4 + 2))
485 0 : return false;
486 :
487 : /* skip attribute length */
488 12119 : cb.read_u4();
489 :
490 : /* number of records */
491 12119 : c->innerclasscount = cb.read_u2();
492 :
493 12119 : if (!cb.check_size((2 + 2 + 2 + 2) * c->innerclasscount))
494 0 : return false;
495 :
496 : /* allocate memory for innerclass structure */
497 12119 : c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
498 :
499 42226 : for (int j = 0; j < c->innerclasscount; j++) {
500 : /* The innerclass structure contains a class with an encoded
501 : name, its defining scope, its simple name and a bitmask of
502 : the access flags. */
503 :
504 30107 : innerclassinfo *info = c->innerclass + j;
505 :
506 30107 : inner.ref = (constant_classref*) innerclass_getconstant(c, cb.read_u2(), CONSTANT_Class);
507 30107 : outer.ref = (constant_classref*) innerclass_getconstant(c, cb.read_u2(), CONSTANT_Class);
508 30107 : Utf8String name = (utf*) innerclass_getconstant(c, cb.read_u2(), CONSTANT_Utf8);
509 30107 : uint16_t flags = cb.read_u2();
510 :
511 : /* If the current inner-class is the currently loaded
512 : class check for some special flags. */
513 :
514 30107 : if (inner.ref->name == c->name) {
515 : /* If an inner-class is not a member, its
516 : outer-class is NULL. */
517 :
518 6441 : if (outer.ref != NULL) {
519 4920 : c->flags |= ACC_CLASS_MEMBER;
520 :
521 : /* A member class doesn't have an
522 : EnclosingMethod attribute, so set the
523 : enclosing-class to be the same as the
524 : declaring-class. */
525 :
526 4920 : c->declaringclass = outer;
527 4920 : c->enclosingclass = outer;
528 : }
529 :
530 : /* If an inner-class is anonymous, its name is
531 : NULL. */
532 :
533 6441 : if (name == NULL)
534 1528 : c->flags |= ACC_CLASS_ANONYMOUS;
535 : }
536 :
537 30107 : info->inner_class = inner;
538 30107 : info->outer_class = outer;
539 30107 : info->name = name;
540 30107 : info->flags = flags;
541 : }
542 : }
543 48397 : else if (attribute_name == utf8::SourceFile) {
544 : /* SourceFile */
545 :
546 35765 : if (!class_load_attribute_sourcefile(cb))
547 0 : return false;
548 : }
549 : #if defined(ENABLE_JAVASE)
550 12632 : else if (attribute_name == utf8::EnclosingMethod) {
551 : /* EnclosingMethod */
552 :
553 1530 : if (!class_load_attribute_enclosingmethod(cb))
554 0 : return false;
555 : }
556 11102 : else if (attribute_name == utf8::Signature) {
557 : /* Signature */
558 :
559 : // TODO: change classinfo.signature to Utf8String
560 : // and use it directly
561 :
562 11061 : Utf8String signature = c->signature;
563 :
564 11061 : if (!loader_load_attribute_signature(cb, signature)) {
565 0 : return false;
566 : }
567 :
568 11061 : c->signature = signature;
569 : }
570 : #endif
571 :
572 : #if defined(ENABLE_ANNOTATIONS)
573 41 : else if (attribute_name == utf8::RuntimeVisibleAnnotations) {
574 : /* RuntimeVisibleAnnotations */
575 40 : if (!annotation_load_class_attribute_runtimevisibleannotations(cb))
576 0 : return false;
577 : }
578 1 : else if (attribute_name == utf8::RuntimeInvisibleAnnotations) {
579 : /* RuntimeInvisibleAnnotations */
580 1 : if (!annotation_load_class_attribute_runtimeinvisibleannotations(cb))
581 0 : return false;
582 : }
583 : #endif
584 :
585 : else {
586 : /* unknown attribute */
587 :
588 0 : if (!loader_skip_attribute_body(cb))
589 0 : return false;
590 : }
591 : }
592 :
593 35788 : return true;
594 : }
595 :
596 :
597 : /* class_freepool **************************************************************
598 :
599 : Frees all resources used by this classes Constant Pool.
600 :
601 : *******************************************************************************/
602 :
603 2 : static void class_freecpool(classinfo *c)
604 : {
605 2 : if (c->cptags && c->cpinfos) {
606 49 : for (int32_t idx = 0; idx < c->cpcount; idx++) {
607 47 : ConstantPoolTag tag = (ConstantPoolTag) c->cptags[idx];
608 47 : void *info = c->cpinfos[idx];
609 :
610 47 : if (info != NULL) {
611 41 : switch (tag) {
612 : case CONSTANT_Class:
613 : case CONSTANT_ClassName:
614 : case CONSTANT_String:
615 : case CONSTANT_Utf8:
616 : // these live forever
617 37 : break;
618 :
619 : case CONSTANT_Fieldref:
620 : case CONSTANT_Methodref:
621 : case CONSTANT_InterfaceMethodref:
622 0 : FREE(info, constant_FMIref);
623 0 : break;
624 : case CONSTANT_Integer:
625 0 : FREE(info, int32_t);
626 0 : break;
627 : case CONSTANT_Float:
628 0 : FREE(info, float);
629 0 : break;
630 : case CONSTANT_Long:
631 0 : FREE(info, int64_t);
632 0 : break;
633 : case CONSTANT_Double:
634 0 : FREE(info, double);
635 0 : break;
636 : case CONSTANT_NameAndType:
637 4 : FREE(info, constant_nameandtype);
638 4 : break;
639 :
640 : case CONSTANT_MethodType:
641 0 : delete ((constant_MethodType*) info);
642 0 : break;
643 : case CONSTANT_MethodHandle:
644 0 : delete ((constant_MethodHandle*) info);
645 0 : break;
646 : case CONSTANT_InvokeDynamic:
647 0 : delete ((constant_InvokeDynamic*) info);
648 0 : break;
649 :
650 : case CONSTANT_UNUSED:
651 0 : assert(info == 0);
652 : break;
653 : }
654 : }
655 : }
656 : }
657 :
658 2 : if (c->cptags)
659 2 : MFREE(c->cptags, u1, c->cpcount);
660 :
661 2 : if (c->cpinfos)
662 2 : MFREE(c->cpinfos, void*, c->cpcount);
663 2 : }
664 :
665 :
666 : /* class_getconstant ***********************************************************
667 :
668 : Retrieves the value at position 'pos' of the constantpool of a
669 : class. If the type of the value is other than 'ctype', an error is
670 : thrown.
671 :
672 : *******************************************************************************/
673 :
674 7223900 : void* class_getconstant(classinfo *c, u4 pos, ConstantPoolTag ctype)
675 : {
676 : // check index and type of constantpool entry
677 : // (pos == 0 is caught by type comparison)
678 :
679 7223900 : if ((((int32_t)pos) >= c->cpcount) || (c->cptags[pos] != ctype)) {
680 : // this is the slow path,
681 : // we can afford to repeat the separate checks for a better error message
682 :
683 0 : if ((pos == 0) || (((int32_t)pos) >= c->cpcount)) {
684 0 : exceptions_throw_classformaterror(c, "Illegal constant pool index: %u", pos);
685 0 : } else if (c->cptags[pos] != ctype) {
686 0 : exceptions_throw_classformaterror(c, "Illegal constant pool type %u (expected %u)", ctype, c->cptags[pos]);
687 : }
688 :
689 0 : assert(exceptions_get_exception());
690 0 : return NULL;
691 : }
692 :
693 7223900 : return c->cpinfos[pos];
694 : }
695 :
696 :
697 : /* innerclass_getconstant ******************************************************
698 :
699 : Like class_getconstant, but if cptags is ZERO, null is returned.
700 :
701 : *******************************************************************************/
702 :
703 93381 : void* innerclass_getconstant(classinfo *c, u4 pos, ConstantPoolTag ctype)
704 : {
705 : /* invalid position in constantpool */
706 :
707 93381 : if (((int32_t)pos) >= c->cpcount) {
708 0 : exceptions_throw_classformaterror(c, "Illegal constant pool index: %u", pos);
709 0 : return NULL;
710 : }
711 :
712 : /* constantpool entry of type 0 */
713 :
714 93381 : if (c->cptags[pos] == 0)
715 11606 : return NULL;
716 :
717 : /* check type of constantpool entry */
718 :
719 81775 : if (c->cptags[pos] != ctype) {
720 0 : exceptions_throw_classformaterror(c, "Illegal constant pool type %u (expected %u)", ctype, c->cptags[pos]);
721 0 : return NULL;
722 : }
723 :
724 81775 : return c->cpinfos[pos];
725 : }
726 :
727 :
728 : /* class_free ******************************************************************
729 :
730 : Frees all resources used by the class.
731 :
732 : *******************************************************************************/
733 :
734 2 : void class_free(classinfo *c)
735 : {
736 2 : class_freecpool(c);
737 :
738 2 : if (c->interfaces != NULL)
739 1 : MFREE(c->interfaces, classinfo*, c->interfacescount);
740 :
741 2 : if (c->fields) {
742 4 : for (int32_t i = 0; i < c->fieldscount; i++)
743 2 : field_free(&(c->fields[i]));
744 2 : MFREE(c->fields, fieldinfo, c->fieldscount);
745 : }
746 :
747 2 : if (c->methods) {
748 4 : for (int32_t i = 0; i < c->methodscount; i++)
749 2 : method_free(&(c->methods[i]));
750 2 : MFREE(c->methods, methodinfo, c->methodscount);
751 : }
752 :
753 2 : if (vftbl_t *v = c->vftbl) {
754 0 : if (v->arraydesc)
755 0 : mem_free(v->arraydesc,sizeof(arraydescriptor));
756 :
757 0 : for (int32_t i = 0; i < v->interfacetablelength; i++) {
758 0 : MFREE(v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
759 : }
760 0 : MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
761 :
762 : int32_t i = sizeof(vftbl_t)
763 : + sizeof(methodptr) * (v->vftbllength - 1)
764 0 : + sizeof(methodptr*) * (v->interfacetablelength - (v->interfacetablelength > 0));
765 0 : methodptr *m = ((methodptr*) v) - (v->interfacetablelength - 1) * (v->interfacetablelength > 1);
766 0 : mem_free(m, i);
767 : }
768 :
769 2 : if (c->innerclass)
770 0 : MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
771 :
772 : /* if (c->classvftbl)
773 : mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
774 :
775 : /* GCFREE(c); */
776 2 : }
777 :
778 :
779 : /* get_array_class *************************************************************
780 :
781 : Returns the array class with the given name for the given
782 : classloader, or NULL if an exception occurred.
783 :
784 : Note: This function does eager loading.
785 :
786 : *******************************************************************************/
787 :
788 319867 : static classinfo *get_array_class(Utf8String name,classloader_t *initloader,
789 : classloader_t *defloader,bool link)
790 : {
791 : classinfo *c;
792 :
793 : /* lookup this class in the classcache */
794 319867 : c = classcache_lookup(initloader,name);
795 319867 : if (!c)
796 3477 : c = classcache_lookup_defined(defloader,name);
797 :
798 319867 : if (!c) {
799 : /* we have to create it */
800 3477 : c = class_create_classinfo(name);
801 3477 : c = load_newly_created_array(c,initloader);
802 3477 : if (c == NULL)
803 0 : return NULL;
804 : }
805 :
806 319867 : assert(c);
807 319867 : assert(c->state & CLASS_LOADED);
808 319867 : assert(c->classloader == defloader);
809 :
810 319867 : if (link && !(c->state & CLASS_LINKED))
811 1319 : if (!link_class(c))
812 1 : return NULL;
813 :
814 319866 : assert(!link || (c->state & CLASS_LINKED));
815 :
816 319866 : return c;
817 : }
818 :
819 :
820 : /* class_array_of **************************************************************
821 :
822 : Returns an array class with the given component class. The array
823 : class is dynamically created if neccessary.
824 :
825 : *******************************************************************************/
826 :
827 317893 : classinfo *class_array_of(classinfo *component, bool link)
828 : {
829 : classloader_t *cl;
830 : s4 namelen;
831 : char *namebuf;
832 317893 : Utf8String u;
833 : classinfo *c;
834 :
835 317893 : Utf8String component_name = component->name;
836 :
837 317893 : cl = component->classloader;
838 :
839 : /* Assemble the array class name */
840 317893 : namelen = component_name.size();
841 :
842 317893 : if (component_name[0] == '[') {
843 : /* the component is itself an array */
844 14079 : namebuf = MNEW(char, namelen + 1);
845 14079 : namebuf[0] = '[';
846 14079 : MCOPY(namebuf + 1, component_name.begin(), char, namelen);
847 14079 : namelen++;
848 : }
849 : else {
850 : /* the component is a non-array class */
851 303814 : namebuf = MNEW(char, namelen + 3);
852 303814 : namebuf[0] = '[';
853 303814 : namebuf[1] = 'L';
854 303814 : MCOPY(namebuf + 2, component_name.begin(), char, namelen);
855 303814 : namebuf[2 + namelen] = ';';
856 303814 : namelen += 3;
857 : }
858 :
859 317893 : u = Utf8String::from_utf8(namebuf, namelen);
860 :
861 317893 : MFREE(namebuf, char, namelen);
862 :
863 317893 : c = get_array_class(u, cl, cl, link);
864 :
865 317893 : return c;
866 : }
867 :
868 :
869 : /* class_multiarray_of *********************************************************
870 :
871 : Returns an array class with the given dimension and element class.
872 : The array class is dynamically created if neccessary.
873 :
874 : *******************************************************************************/
875 :
876 1974 : classinfo *class_multiarray_of(s4 dim, classinfo *element, bool link)
877 : {
878 : s4 namelen;
879 : char *namebuf;
880 : classinfo *c;
881 :
882 1974 : Utf8String element_name = element->name;
883 :
884 1974 : if (dim < 1) {
885 0 : log_text("Invalid array dimension requested");
886 0 : assert(0);
887 : }
888 :
889 : /* Assemble the array class name */
890 1974 : namelen = element_name.size();
891 :
892 1974 : if (element_name[0] == '[') {
893 : /* the element is itself an array */
894 0 : namebuf = MNEW(char, namelen + dim);
895 0 : memcpy(namebuf + dim, element_name.begin(), namelen);
896 0 : namelen += dim;
897 : }
898 : else {
899 : /* the element is a non-array class */
900 1974 : namebuf = MNEW(char, namelen + 2 + dim);
901 1974 : namebuf[dim] = 'L';
902 1974 : memcpy(namebuf + dim + 1, element_name.begin(), namelen);
903 1974 : namelen += (2 + dim);
904 1974 : namebuf[namelen - 1] = ';';
905 : }
906 1974 : memset(namebuf, '[', dim);
907 :
908 1974 : Utf8String u = Utf8String::from_utf8(namebuf, namelen);
909 :
910 1974 : MFREE(namebuf, char, namelen);
911 :
912 : c = get_array_class(u,
913 : element->classloader,
914 : element->classloader,
915 1974 : link);
916 :
917 1974 : return c;
918 : }
919 :
920 :
921 : /* class_lookup_classref *******************************************************
922 :
923 : Looks up the constant_classref for a given classname in the classref
924 : tables of a class.
925 :
926 : IN:
927 : cls..............the class containing the reference
928 : name.............the name of the class refered to
929 :
930 : RETURN VALUE:
931 : a pointer to a constant_classref, or
932 : NULL if the reference was not found
933 :
934 : *******************************************************************************/
935 :
936 505623 : constant_classref *class_lookup_classref(classinfo *cls, Utf8String name)
937 : {
938 : constant_classref *ref;
939 : extra_classref *xref;
940 : int count;
941 :
942 505623 : assert(cls);
943 505623 : assert(name);
944 505623 : assert(!cls->classrefcount || cls->classrefs);
945 :
946 : /* first search the main classref table */
947 505623 : count = cls->classrefcount;
948 505623 : ref = cls->classrefs;
949 1273961 : for (; count; --count, ++ref)
950 1266574 : if (ref->name == name)
951 498236 : return ref;
952 :
953 : /* next try the list of extra classrefs */
954 7428 : for (xref = cls->extclassrefs; xref; xref = xref->next) {
955 3184 : if (xref->classref.name == name)
956 3143 : return &(xref->classref);
957 : }
958 :
959 : /* not found */
960 4244 : return NULL;
961 : }
962 :
963 :
964 : /* class_get_classref **********************************************************
965 :
966 : Returns the constant_classref for a given classname.
967 :
968 : IN:
969 : cls..............the class containing the reference
970 : name.............the name of the class refered to
971 :
972 : RETURN VALUE:
973 : a pointer to a constant_classref (never NULL)
974 :
975 : NOTE:
976 : The given name is not checked for validity!
977 :
978 : *******************************************************************************/
979 :
980 505623 : constant_classref *class_get_classref(classinfo *cls, Utf8String name)
981 : {
982 505623 : assert(cls);
983 505623 : assert(name);
984 :
985 505623 : if (constant_classref *ref = class_lookup_classref(cls,name))
986 501379 : return ref;
987 :
988 4244 : extra_classref *xref = new (MemAlloc) extra_classref(cls->extclassrefs, cls, name);
989 :
990 4244 : cls->extclassrefs = xref;
991 :
992 4244 : return &(xref->classref);
993 : }
994 :
995 :
996 : /* class_get_self_classref *****************************************************
997 :
998 : Returns the constant_classref to the class itself.
999 :
1000 : IN:
1001 : cls..............the class containing the reference
1002 :
1003 : RETURN VALUE:
1004 : a pointer to a constant_classref (never NULL)
1005 :
1006 : *******************************************************************************/
1007 :
1008 478208 : constant_classref *class_get_self_classref(classinfo *cls)
1009 : {
1010 : /* XXX this should be done in a faster way. Maybe always make */
1011 : /* the classref of index 0 a self reference. */
1012 478208 : return class_get_classref(cls,cls->name);
1013 : }
1014 :
1015 : /* class_get_classref_multiarray_of ********************************************
1016 :
1017 : Returns an array type reference with the given dimension and element class
1018 : reference.
1019 :
1020 : IN:
1021 : dim..............the requested dimension
1022 : dim must be in [1;255]. This is NOT checked!
1023 : ref..............the component class reference
1024 :
1025 : RETURN VALUE:
1026 : a pointer to the class reference for the array type
1027 :
1028 : NOTE:
1029 : The referer of `ref` is used as the referer for the new classref.
1030 :
1031 : *******************************************************************************/
1032 :
1033 9150 : constant_classref *class_get_classref_multiarray_of(s4 dim, constant_classref *ref)
1034 : {
1035 : s4 namelen;
1036 : char *namebuf;
1037 : constant_classref *cr;
1038 :
1039 9150 : Utf8String refname = ref->name;
1040 :
1041 9150 : assert(ref);
1042 9150 : assert(dim >= 1 && dim <= 255);
1043 :
1044 : /* Assemble the array class name */
1045 9150 : namelen = refname.size();
1046 :
1047 9150 : if (refname[0] == '[') {
1048 : /* the element is itself an array */
1049 866 : namebuf = MNEW(char, namelen + dim);
1050 866 : memcpy(namebuf + dim, refname.begin(), namelen);
1051 866 : namelen += dim;
1052 : }
1053 : else {
1054 : /* the element is a non-array class */
1055 8284 : namebuf = MNEW(char, namelen + 2 + dim);
1056 8284 : namebuf[dim] = 'L';
1057 8284 : memcpy(namebuf + dim + 1, refname.begin(), namelen);
1058 8284 : namelen += (2 + dim);
1059 8284 : namebuf[namelen - 1] = ';';
1060 : }
1061 9150 : memset(namebuf, '[', dim);
1062 :
1063 9150 : Utf8String u = Utf8String::from_utf8(namebuf, namelen);
1064 :
1065 9150 : MFREE(namebuf, char, namelen);
1066 :
1067 9150 : cr = class_get_classref(ref->referer, u);
1068 :
1069 9150 : return cr;
1070 : }
1071 :
1072 :
1073 : /* class_get_classref_component_of *********************************************
1074 :
1075 : Returns the component classref of a given array type reference
1076 :
1077 : IN:
1078 : ref..............the array type reference
1079 :
1080 : RETURN VALUE:
1081 : a reference to the component class, or
1082 : NULL if `ref` is not an object array type reference
1083 :
1084 : NOTE:
1085 : The referer of `ref` is used as the referer for the new classref.
1086 :
1087 : *******************************************************************************/
1088 :
1089 181 : constant_classref *class_get_classref_component_of(constant_classref *ref)
1090 : {
1091 181 : assert(ref);
1092 :
1093 181 : Utf8String name = ref->name;
1094 181 : size_t start = 1;
1095 181 : size_t end = name.size() - 1;
1096 :
1097 181 : if (name[0] != '[')
1098 0 : return NULL;
1099 :
1100 181 : if (name[1] == 'L') {
1101 179 : start += 1;
1102 179 : end -= 2;
1103 : }
1104 2 : else if (name[1] != '[') {
1105 0 : return NULL;
1106 : }
1107 :
1108 181 : return class_get_classref(ref->referer, name.substring(start, end));
1109 : }
1110 :
1111 :
1112 : /* class_findmethod ************************************************************
1113 :
1114 : Searches a 'classinfo' structure for a method having the given name
1115 : and descriptor. If descriptor is NULL, it is ignored.
1116 :
1117 : *******************************************************************************/
1118 :
1119 279618 : methodinfo *class_findmethod(classinfo *c, Utf8String name, Utf8String desc)
1120 : {
1121 3111609 : for (int32_t i = 0; i < c->methodscount; i++) {
1122 3040325 : methodinfo *m = &(c->methods[i]);
1123 :
1124 3040325 : if ((m->name == name) && ((desc == NULL) || (m->descriptor == desc)))
1125 208334 : return m;
1126 : }
1127 :
1128 71284 : return NULL;
1129 : }
1130 :
1131 :
1132 : /* class_resolvemethod *********************************************************
1133 :
1134 : Searches a class and it's super classes for a method.
1135 :
1136 : Superinterfaces are *not* searched.
1137 :
1138 : *******************************************************************************/
1139 :
1140 150642 : methodinfo *class_resolvemethod(classinfo *c, Utf8String name, Utf8String desc)
1141 : {
1142 314160 : while (c) {
1143 163518 : methodinfo *m = class_findmethod(c, name, desc);
1144 :
1145 163518 : if (m)
1146 150642 : return m;
1147 :
1148 : /* JVM Specification bug:
1149 :
1150 : It is important NOT to resolve special <init> and <clinit>
1151 : methods to super classes or interfaces; yet, this is not
1152 : explicited in the specification. Section 5.4.3.3 should be
1153 : updated appropriately. */
1154 :
1155 12876 : if (name == utf8::init || name == utf8::clinit)
1156 0 : return NULL;
1157 :
1158 12876 : c = c->super;
1159 : }
1160 :
1161 0 : return NULL;
1162 : }
1163 :
1164 :
1165 : /* class_resolveinterfacemethod_intern *****************************************
1166 :
1167 : Internally used helper function. Do not use this directly.
1168 :
1169 : *******************************************************************************/
1170 :
1171 5625 : static methodinfo *class_resolveinterfacemethod_intern(classinfo *c,
1172 : Utf8String name, Utf8String desc)
1173 : {
1174 : /* try to find the method in the class */
1175 :
1176 5625 : methodinfo *m = class_findmethod(c, name, desc);
1177 :
1178 5625 : if (m != NULL)
1179 5625 : return m;
1180 :
1181 : /* No method found? Try the super interfaces. */
1182 :
1183 0 : for (int32_t i = 0; i < c->interfacescount; i++) {
1184 0 : methodinfo *m = class_resolveinterfacemethod_intern(c->interfaces[i], name, desc);
1185 :
1186 0 : if (m != NULL)
1187 0 : return m;
1188 : }
1189 :
1190 : /* no method found */
1191 :
1192 0 : return NULL;
1193 : }
1194 :
1195 :
1196 : /* class_resolveclassmethod ****************************************************
1197 :
1198 : Resolves a reference from REFERER to a method with NAME and DESC in
1199 : class C.
1200 :
1201 : If the method cannot be resolved the return value is NULL. If
1202 : EXCEPT is true *exceptionptr is set, too.
1203 :
1204 : *******************************************************************************/
1205 :
1206 147634 : methodinfo *class_resolveclassmethod(classinfo *c, Utf8String name, Utf8String desc,
1207 : classinfo *referer, bool throwexception)
1208 : {
1209 : /* try class c and its superclasses */
1210 :
1211 147634 : classinfo *cls = c;
1212 :
1213 147634 : methodinfo *m = class_resolvemethod(cls, name, desc);
1214 :
1215 147634 : if (m != NULL)
1216 147634 : goto found;
1217 :
1218 : /* Try the super interfaces. */
1219 :
1220 0 : for (int32_t i = 0; i < c->interfacescount; i++) {
1221 0 : methodinfo *m = class_resolveinterfacemethod_intern(c->interfaces[i], name, desc);
1222 :
1223 0 : if (m != NULL)
1224 0 : goto found;
1225 : }
1226 :
1227 0 : if (throwexception)
1228 0 : exceptions_throw_nosuchmethoderror(c, name, desc);
1229 :
1230 0 : return NULL;
1231 :
1232 : found:
1233 147634 : if ((m->flags & ACC_ABSTRACT) && !(c->flags & ACC_ABSTRACT)) {
1234 0 : if (throwexception)
1235 0 : exceptions_throw_abstractmethoderror();
1236 :
1237 0 : return NULL;
1238 : }
1239 :
1240 : /* XXX check access rights */
1241 :
1242 147634 : return m;
1243 : }
1244 :
1245 :
1246 : /* class_resolveinterfacemethod ************************************************
1247 :
1248 : Resolves a reference from REFERER to a method with NAME and DESC in
1249 : interface C.
1250 :
1251 : If the method cannot be resolved the return value is NULL. If
1252 : EXCEPT is true *exceptionptr is set, too.
1253 :
1254 : *******************************************************************************/
1255 :
1256 5625 : methodinfo *class_resolveinterfacemethod(classinfo *c, Utf8String name, Utf8String desc,
1257 : classinfo *referer, bool throwexception)
1258 : {
1259 : methodinfo *mi;
1260 :
1261 5625 : if (!(c->flags & ACC_INTERFACE)) {
1262 0 : if (throwexception)
1263 0 : exceptions_throw_incompatibleclasschangeerror(c, "Not an interface");
1264 :
1265 0 : return NULL;
1266 : }
1267 :
1268 5625 : mi = class_resolveinterfacemethod_intern(c, name, desc);
1269 :
1270 5625 : if (mi != NULL)
1271 5625 : return mi;
1272 :
1273 : /* try class java.lang.Object */
1274 :
1275 0 : mi = class_findmethod(class_java_lang_Object, name, desc);
1276 :
1277 0 : if (mi != NULL)
1278 0 : return mi;
1279 :
1280 0 : if (throwexception)
1281 0 : exceptions_throw_nosuchmethoderror(c, name, desc);
1282 :
1283 0 : return NULL;
1284 : }
1285 :
1286 :
1287 : /* class_findfield *************************************************************
1288 :
1289 : Searches for field with specified name and type in a classinfo
1290 : structure. If no such field is found NULL is returned.
1291 :
1292 : *******************************************************************************/
1293 :
1294 608 : fieldinfo *class_findfield(classinfo *c, Utf8String name, Utf8String desc)
1295 : {
1296 1339 : for (int32_t i = 0; i < c->fieldscount; i++)
1297 1339 : if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
1298 608 : return &(c->fields[i]);
1299 :
1300 0 : if (c->super != NULL)
1301 0 : return class_findfield(c->super, name, desc);
1302 :
1303 0 : return NULL;
1304 : }
1305 :
1306 :
1307 : /* class_findfield_approx ******************************************************
1308 :
1309 : Searches in 'classinfo'-structure for a field with the specified
1310 : name.
1311 :
1312 : *******************************************************************************/
1313 :
1314 978 : fieldinfo *class_findfield_by_name(classinfo* c, Utf8String name)
1315 : {
1316 8639 : for (int32_t i = 0; i < c->fieldscount; i++) {
1317 8639 : fieldinfo* f = &(c->fields[i]);
1318 :
1319 8639 : if (f->name == name)
1320 978 : return f;
1321 : }
1322 :
1323 : // Field not found.
1324 0 : exceptions_throw_nosuchfielderror(c, name);
1325 0 : return NULL;
1326 : }
1327 :
1328 :
1329 : /****************** Function: class_resolvefield_int ***************************
1330 :
1331 : This is an internally used helper function. Do not use this directly.
1332 :
1333 : Tries to resolve a field having the given name and type.
1334 : If the field cannot be resolved, NULL is returned.
1335 :
1336 : *******************************************************************************/
1337 :
1338 80620 : static fieldinfo *class_resolvefield_int(classinfo *c, Utf8String name, Utf8String desc)
1339 : {
1340 : /* search for field in class c */
1341 :
1342 451722 : for (int32_t i = 0; i < c->fieldscount; i++) {
1343 438757 : if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) {
1344 67655 : return &(c->fields[i]);
1345 : }
1346 : }
1347 :
1348 : /* Try super interfaces recursively. */
1349 :
1350 17676 : for (int32_t i = 0; i < c->interfacescount; i++) {
1351 4715 : fieldinfo *fi = class_resolvefield_int(c->interfaces[i], name, desc);
1352 :
1353 4715 : if (fi != NULL)
1354 4 : return fi;
1355 : }
1356 :
1357 : /* Try super class. */
1358 :
1359 12961 : if (c->super != NULL)
1360 8246 : return class_resolvefield_int(c->super, name, desc);
1361 :
1362 : /* not found */
1363 :
1364 4715 : return NULL;
1365 : }
1366 :
1367 :
1368 : /********************* Function: class_resolvefield ***************************
1369 :
1370 : Resolves a reference from REFERER to a field with NAME and DESC in class C.
1371 :
1372 : If the field cannot be resolved, an exception is thrown and the
1373 : return value is NULL.
1374 :
1375 : *******************************************************************************/
1376 :
1377 67659 : fieldinfo *class_resolvefield(classinfo *c, Utf8String name, Utf8String desc, classinfo *referer)
1378 : {
1379 67659 : fieldinfo *fi = class_resolvefield_int(c, name, desc);
1380 :
1381 67659 : if (!fi) {
1382 4 : exceptions_throw_nosuchfielderror(c, name);
1383 4 : return NULL;
1384 : }
1385 :
1386 : /* XXX check access rights */
1387 :
1388 67655 : return fi;
1389 : }
1390 :
1391 :
1392 : /* class_issubclass ************************************************************
1393 :
1394 : Checks if sub is a descendant of super.
1395 :
1396 : *******************************************************************************/
1397 :
1398 156698 : bool class_issubclass(classinfo *sub, classinfo *super)
1399 : {
1400 156698 : classinfo *c = sub;
1401 :
1402 118359 : for (;;) {
1403 : /* We reached java/lang/Object and did not find the requested
1404 : super class. */
1405 :
1406 275057 : if (c == NULL)
1407 20 : return false;
1408 :
1409 : /* We found the requested super class. */
1410 :
1411 275037 : if (c == super)
1412 156678 : return true;
1413 :
1414 118359 : c = c->super;
1415 : }
1416 : }
1417 :
1418 :
1419 : /* class_isanysubclass *********************************************************
1420 :
1421 : Checks a subclass relation between two classes. Implemented
1422 : interfaces are interpreted as super classes.
1423 :
1424 : Return value: 1 ... sub is subclass of super
1425 : 0 ... otherwise
1426 :
1427 : *******************************************************************************/
1428 :
1429 138127 : bool class_isanysubclass(classinfo *sub, classinfo *super)
1430 : {
1431 : bool result;
1432 :
1433 : /* This is the trivial case. */
1434 :
1435 138127 : if (sub == super)
1436 23373 : return true;
1437 :
1438 : /* Primitive classes are only subclasses of themselves. */
1439 :
1440 114754 : if (class_is_primitive(sub) || class_is_primitive(super))
1441 28 : return false;
1442 :
1443 : /* Check for interfaces. */
1444 :
1445 114726 : if (super->flags & ACC_INTERFACE) {
1446 : result = (sub->vftbl->interfacetablelength > super->index) &&
1447 705 : (sub->vftbl->interfacetable[-super->index] != NULL);
1448 : }
1449 : else {
1450 : /* java.lang.Object is the only super class of any
1451 : interface. */
1452 :
1453 114021 : if (sub->state & ACC_INTERFACE)
1454 0 : return (super == class_java_lang_Object);
1455 :
1456 : #if USES_NEW_SUBTYPE
1457 114021 : result = fast_subtype_check(sub->vftbl, super->vftbl);
1458 : #else
1459 : LOCK_CLASSRENUMBER_LOCK;
1460 :
1461 : uint32_t diffval = sub->vftbl->baseval - super->vftbl->baseval;
1462 : result = diffval <= (uint32_t) super->vftbl->diffval;
1463 :
1464 : UNLOCK_CLASSRENUMBER_LOCK;
1465 : #endif
1466 : }
1467 :
1468 114725 : return result;
1469 : }
1470 :
1471 :
1472 : /* class_is_arraycompatible ****************************************************
1473 :
1474 : Checks if two array type descriptors are assignment compatible.
1475 :
1476 : RETURN VALUE:
1477 : true .... target = desc is possible
1478 : false ... otherwise
1479 :
1480 : *******************************************************************************/
1481 :
1482 352209 : bool class_is_arraycompatible(arraydescriptor *desc, arraydescriptor *target)
1483 : {
1484 352209 : if (desc == target)
1485 333182 : return true;
1486 :
1487 19027 : if (desc->arraytype != target->arraytype)
1488 3268 : return false;
1489 :
1490 15759 : if (desc->arraytype != ARRAYTYPE_OBJECT)
1491 0 : return true;
1492 :
1493 : /* {both arrays are arrays of references} */
1494 :
1495 15759 : if (desc->dimension == target->dimension) {
1496 2459 : if (!desc->elementvftbl)
1497 1 : return false;
1498 :
1499 : /* an array which contains elements of interface types is
1500 : allowed to be casted to array of Object (JOWENN) */
1501 :
1502 2458 : if ((desc->elementvftbl->baseval < 0) &&
1503 : (target->elementvftbl->baseval == 1))
1504 805 : return true;
1505 :
1506 1653 : return class_isanysubclass(desc->elementvftbl->clazz, target->elementvftbl->clazz);
1507 : }
1508 :
1509 13300 : if (desc->dimension < target->dimension)
1510 0 : return false;
1511 :
1512 : /* {desc has higher dimension than target} */
1513 :
1514 13300 : return class_isanysubclass(pseudo_class_Arraystub, target->elementvftbl->clazz);
1515 : }
1516 :
1517 :
1518 : /* class_is_assignable_from ****************************************************
1519 :
1520 : Return whether an instance of the "from" class parameter would be
1521 : an instance of this class "to" as well.
1522 :
1523 : ARGUMENTS:
1524 : to ..... class
1525 : from ... class
1526 :
1527 : RETURN:
1528 : true .... is assignable
1529 : false ... is not assignable
1530 :
1531 : *******************************************************************************/
1532 :
1533 1027 : bool class_is_assignable_from(classinfo *to, classinfo *from)
1534 : {
1535 1027 : if (!(to->state & CLASS_LINKED))
1536 0 : if (!link_class(to))
1537 0 : return false;
1538 :
1539 1027 : if (!(from->state & CLASS_LINKED))
1540 0 : if (!link_class(from))
1541 0 : return false;
1542 :
1543 : /* Decide whether we are dealing with array types or object types. */
1544 :
1545 1027 : if (class_is_array(to) && class_is_array(from))
1546 0 : return class_is_arraycompatible(from->vftbl->arraydesc, to->vftbl->arraydesc);
1547 : else
1548 1027 : return class_isanysubclass(from, to);
1549 : }
1550 :
1551 :
1552 : /* class_is_instance ***********************************************************
1553 :
1554 : Return if the given Java object is an instance of the given class.
1555 :
1556 : ARGUMENTS:
1557 : c ... class
1558 : h ... Java object
1559 :
1560 : RETURN:
1561 : true .... is instance
1562 : false ... is not instance
1563 :
1564 : *******************************************************************************/
1565 :
1566 773 : bool class_is_instance(classinfo *c, java_handle_t *h)
1567 : {
1568 773 : if (!(c->state & CLASS_LINKED))
1569 1 : if (!link_class(c))
1570 0 : return false;
1571 :
1572 : /* Decide whether we are dealing with array types or object types. */
1573 :
1574 773 : if (class_is_array(c))
1575 154 : return builtin_arrayinstanceof(h, c);
1576 : else
1577 619 : return builtin_instanceof(h, c);
1578 : }
1579 :
1580 :
1581 : /* class_get_componenttype *****************************************************
1582 :
1583 : Return the component class of the given class. If the given class
1584 : is not an array, return NULL.
1585 :
1586 : *******************************************************************************/
1587 :
1588 2161 : classinfo *class_get_componenttype(classinfo *c)
1589 : {
1590 : classinfo *component;
1591 : arraydescriptor *ad;
1592 :
1593 : /* XXX maybe we could find a way to do this without linking. */
1594 : /* This way should be safe and easy, however. */
1595 :
1596 2161 : if (!(c->state & CLASS_LINKED))
1597 3 : if (!link_class(c))
1598 0 : return NULL;
1599 :
1600 2161 : ad = c->vftbl->arraydesc;
1601 :
1602 2161 : if (ad == NULL)
1603 0 : return NULL;
1604 :
1605 2161 : if (ad->arraytype == ARRAYTYPE_OBJECT)
1606 2110 : component = ad->componentvftbl->clazz;
1607 : else
1608 51 : component = Primitive::get_class_by_type(ad->arraytype);
1609 :
1610 2161 : return component;
1611 : }
1612 :
1613 :
1614 : /* class_get_declaredclasses ***************************************************
1615 :
1616 : Return an array of declared classes of the given class.
1617 :
1618 : *******************************************************************************/
1619 :
1620 0 : java_handle_objectarray_t *class_get_declaredclasses(classinfo *c, bool publicOnly)
1621 : {
1622 0 : int declaredclasscount = 0; // number of declared classes
1623 :
1624 0 : if (!class_is_primitive(c) && !class_is_array(c)) {
1625 : /* Determine number of declared classes. */
1626 :
1627 0 : for (uint16_t i = 0; i < c->innerclasscount; i++) {
1628 : /* Get outer-class. If the inner-class is not a member
1629 : class, the outer-class is NULL. */
1630 :
1631 0 : classref_or_classinfo outer = c->innerclass[i].outer_class;
1632 :
1633 0 : if (outer.any == NULL)
1634 0 : continue;
1635 :
1636 : /* Check if outer-class is a classref or a real class and
1637 : get the class name from the structure. */
1638 :
1639 0 : Utf8String outername = CLASSREF_OR_CLASSINFO_NAME(outer);
1640 :
1641 : /* Outer class is this class. */
1642 :
1643 0 : if ((outername == c->name) &&
1644 0 : ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC)))
1645 0 : declaredclasscount++;
1646 : }
1647 : }
1648 :
1649 : /* Allocate Class[] and check for OOM. */
1650 :
1651 0 : ClassArray declaredclasses(declaredclasscount);
1652 :
1653 0 : if (declaredclasses.is_null())
1654 0 : return NULL;
1655 :
1656 0 : for (uint16_t i = 0, pos = 0; i < c->innerclasscount; i++) {
1657 0 : classref_or_classinfo inner = c->innerclass[i].inner_class;
1658 0 : classref_or_classinfo outer = c->innerclass[i].outer_class;
1659 :
1660 : /* Get outer-class. If the inner-class is not a member class,
1661 : the outer-class is NULL. */
1662 :
1663 0 : if (outer.any == NULL)
1664 0 : continue;
1665 :
1666 : /* Check if outer_class is a classref or a real class and get
1667 : the class name from the structure. */
1668 :
1669 0 : Utf8String outername = CLASSREF_OR_CLASSINFO_NAME(outer);
1670 :
1671 : /* Outer class is this class. */
1672 :
1673 0 : if ((outername == c->name) &&
1674 0 : ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC))) {
1675 :
1676 0 : classinfo *ic = resolve_classref_or_classinfo_eager(inner, false);
1677 :
1678 0 : if (ic == NULL)
1679 0 : return NULL;
1680 :
1681 0 : if (!(ic->state & CLASS_LINKED))
1682 0 : if (!link_class(ic))
1683 0 : return NULL;
1684 :
1685 0 : declaredclasses.set_element(pos++, ic);
1686 : }
1687 : }
1688 :
1689 0 : return declaredclasses.get_handle();
1690 : }
1691 :
1692 :
1693 : /**
1694 : * Return an array of declared constructors of the given class.
1695 : *
1696 : * @param c class to get the constructors of
1697 : * @param publicOnly show only public fields
1698 : *
1699 : * @return array of java.lang.reflect.Constructor
1700 : */
1701 : #if defined(ENABLE_JAVASE)
1702 566 : java_handle_objectarray_t *class_get_declaredconstructors(classinfo *c, bool publicOnly)
1703 : {
1704 : /* Determine number of constructors. */
1705 :
1706 566 : int count = 0;
1707 :
1708 3433 : for (int32_t i = 0; i < c->methodscount; i++) {
1709 2867 : methodinfo* m = &(c->methods[i]);
1710 :
1711 2867 : if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) && (m->name == utf8::init))
1712 570 : count++;
1713 : }
1714 :
1715 : /* Create array of constructors. */
1716 :
1717 566 : ObjectArray oa(count, class_java_lang_reflect_Constructor);
1718 :
1719 566 : if (oa.is_null())
1720 0 : return NULL;
1721 :
1722 : /* Get the constructors and store them in the array. */
1723 :
1724 3433 : for (int32_t i = 0, index = 0; i < c->methodscount; i++) {
1725 2867 : methodinfo* m = &(c->methods[i]);
1726 :
1727 2867 : if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
1728 : (m->name == utf8::init)) {
1729 : // Create a java.lang.reflect.Constructor object.
1730 :
1731 570 : java_lang_reflect_Constructor rc(m);
1732 :
1733 : /* Store object into array. */
1734 :
1735 570 : oa.set_element(index, rc.get_handle());
1736 570 : index++;
1737 : }
1738 : }
1739 :
1740 566 : return oa.get_handle();
1741 : }
1742 : #endif
1743 :
1744 :
1745 : /* class_get_declaredfields ****************************************************
1746 :
1747 : Return an array of declared fields of the given class.
1748 :
1749 : ARGUMENTS:
1750 : c ............ class to get the fields of
1751 : publicOnly ... show only public fields
1752 :
1753 : RETURN:
1754 : array of java.lang.reflect.Field
1755 :
1756 : *******************************************************************************/
1757 :
1758 : #if defined(ENABLE_JAVASE)
1759 219 : java_handle_objectarray_t *class_get_declaredfields(classinfo *c, bool publicOnly)
1760 : {
1761 : /* Determine number of fields. */
1762 :
1763 219 : int count = 0;
1764 :
1765 1099 : for (int32_t i = 0; i < c->fieldscount; i++)
1766 880 : if ((c->fields[i].flags & ACC_PUBLIC) || (publicOnly == 0))
1767 879 : count++;
1768 :
1769 : /* Create array of fields. */
1770 :
1771 219 : ObjectArray oa(count, class_java_lang_reflect_Field);
1772 :
1773 219 : if (oa.is_null())
1774 0 : return NULL;
1775 :
1776 : /* Get the fields and store them in the array. */
1777 :
1778 1099 : for (int32_t i = 0, index = 0; i < c->fieldscount; i++) {
1779 880 : fieldinfo* f = &(c->fields[i]);
1780 :
1781 880 : if ((f->flags & ACC_PUBLIC) || (publicOnly == 0)) {
1782 : // Create a java.lang.reflect.Field object.
1783 :
1784 879 : java_lang_reflect_Field rf(f);
1785 :
1786 : /* Store object into array. */
1787 :
1788 879 : oa.set_element(index, rf.get_handle());
1789 879 : index++;
1790 : }
1791 : }
1792 :
1793 219 : return oa.get_handle();
1794 : }
1795 : #endif
1796 :
1797 :
1798 : /* class_get_declaredmethods ***************************************************
1799 :
1800 : Return an array of declared methods of the given class.
1801 :
1802 : ARGUMENTS:
1803 : c ............ class to get the methods of
1804 : publicOnly ... show only public methods
1805 :
1806 : RETURN:
1807 : array of java.lang.reflect.Method
1808 :
1809 : *******************************************************************************/
1810 :
1811 : #if defined(ENABLE_JAVASE)
1812 753 : java_handle_objectarray_t *class_get_declaredmethods(classinfo *c, bool publicOnly)
1813 : {
1814 : /* JOWENN: array classes do not declare methods according to mauve
1815 : test. It should be considered, if we should return to my old
1816 : clone method overriding instead of declaring it as a member
1817 : function. */
1818 :
1819 753 : if (class_is_array(c)) {
1820 0 : ObjectArray oa(0, class_java_lang_reflect_Method);
1821 0 : return oa.get_handle();
1822 : }
1823 :
1824 : /* Determine number of methods. */
1825 :
1826 753 : int count = 0;
1827 :
1828 9575 : for (int32_t i = 0; i < c->methodscount; i++) {
1829 8822 : methodinfo* m = &(c->methods[i]);
1830 :
1831 8822 : if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
1832 : ((m->name != utf8::init) && (m->name != utf8::clinit)) &&
1833 : !(m->flags & ACC_MIRANDA))
1834 7930 : count++;
1835 : }
1836 :
1837 : /* Create array of methods. */
1838 :
1839 753 : ObjectArray oa(count, class_java_lang_reflect_Method);
1840 :
1841 753 : if (oa.is_null())
1842 0 : return NULL;
1843 :
1844 : /* Get the methods and store them in the array. */
1845 :
1846 9575 : for (int32_t i = 0, index = 0; i < c->methodscount; i++) {
1847 8822 : methodinfo* m = &(c->methods[i]);
1848 :
1849 8822 : if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
1850 : ((m->name != utf8::init) && (m->name != utf8::clinit)) &&
1851 : !(m->flags & ACC_MIRANDA)) {
1852 : // Create java.lang.reflect.Method object.
1853 :
1854 7930 : java_lang_reflect_Method rm(m);
1855 :
1856 : /* Store object into array. */
1857 :
1858 7930 : oa.set_element(index, rm.get_handle());
1859 7930 : index++;
1860 : }
1861 : }
1862 :
1863 753 : return oa.get_handle();
1864 : }
1865 : #endif
1866 :
1867 :
1868 : /* class_get_declaringclass ****************************************************
1869 :
1870 : If the class or interface given is a member of another class,
1871 : return the declaring class. For array and primitive classes return
1872 : NULL.
1873 :
1874 : *******************************************************************************/
1875 :
1876 14 : classinfo *class_get_declaringclass(classinfo *c)
1877 : {
1878 : classref_or_classinfo cr;
1879 : classinfo *dc;
1880 :
1881 : /* Get declaring class. */
1882 :
1883 14 : cr = c->declaringclass;
1884 :
1885 14 : if (cr.any == NULL)
1886 10 : return NULL;
1887 :
1888 : /* Resolve the class if necessary. */
1889 :
1890 4 : if (cr.is_classref()) {
1891 : /* dc = resolve_classref_eager(cr.ref); */
1892 4 : dc = resolve_classref_or_classinfo_eager(cr, true);
1893 :
1894 4 : if (dc == NULL)
1895 0 : return NULL;
1896 :
1897 : /* Store the resolved class in the class structure. */
1898 :
1899 4 : cr.cls = dc;
1900 : }
1901 :
1902 4 : dc = cr.cls;
1903 :
1904 4 : return dc;
1905 : }
1906 :
1907 :
1908 : /* class_get_enclosingclass ****************************************************
1909 :
1910 : Return the enclosing class for the given class.
1911 :
1912 : *******************************************************************************/
1913 :
1914 42 : classinfo *class_get_enclosingclass(classinfo *c)
1915 : {
1916 : classref_or_classinfo cr;
1917 : classinfo *ec;
1918 :
1919 : /* Get enclosing class. */
1920 :
1921 42 : cr = c->enclosingclass;
1922 :
1923 42 : if (cr.any == NULL)
1924 4 : return NULL;
1925 :
1926 : /* Resolve the class if necessary. */
1927 :
1928 38 : if (cr.is_classref()) {
1929 : /* ec = resolve_classref_eager(cr.ref); */
1930 38 : ec = resolve_classref_or_classinfo_eager(cr, true);
1931 :
1932 38 : if (ec == NULL)
1933 0 : return NULL;
1934 :
1935 : /* Store the resolved class in the class structure. */
1936 :
1937 38 : cr.cls = ec;
1938 : }
1939 :
1940 38 : ec = cr.cls;
1941 :
1942 38 : return ec;
1943 : }
1944 :
1945 :
1946 : /**
1947 : * Return the enclosing constructor as java.lang.reflect.Constructor
1948 : * object for the given class.
1949 : *
1950 : * @param c class to return the enclosing constructor for
1951 : *
1952 : * @return java.lang.reflect.Constructor object of the enclosing
1953 : * constructor
1954 : */
1955 : #if defined(ENABLE_JAVASE)
1956 12 : java_handle_t* class_get_enclosingconstructor(classinfo *c)
1957 : {
1958 12 : methodinfo* m = class_get_enclosingmethod_raw(c);
1959 :
1960 12 : if (m == NULL)
1961 3 : return NULL;
1962 :
1963 : /* Check for <init>. */
1964 :
1965 9 : if (m->name != utf8::init)
1966 3 : return NULL;
1967 :
1968 : // Create a java.lang.reflect.Constructor object.
1969 :
1970 6 : java_lang_reflect_Constructor rc(m);
1971 :
1972 6 : return rc.get_handle();
1973 : }
1974 : #endif
1975 :
1976 :
1977 : /* class_get_enclosingmethod ***************************************************
1978 :
1979 : Return the enclosing method for the given class.
1980 :
1981 : IN:
1982 : c ... class to return the enclosing method for
1983 :
1984 : RETURN:
1985 : methodinfo of the enclosing method
1986 :
1987 : *******************************************************************************/
1988 :
1989 24 : methodinfo *class_get_enclosingmethod_raw(classinfo *c)
1990 : {
1991 : constant_nameandtype *cn;
1992 : classinfo *ec;
1993 : methodinfo *m;
1994 :
1995 : /* get enclosing class and method */
1996 :
1997 24 : ec = class_get_enclosingclass(c);
1998 24 : cn = c->enclosingmethod;
1999 :
2000 : /* check for enclosing class and method */
2001 :
2002 24 : if (ec == NULL)
2003 2 : return NULL;
2004 :
2005 22 : if (cn == NULL)
2006 4 : return NULL;
2007 :
2008 : /* find method in enclosing class */
2009 :
2010 18 : m = class_findmethod(ec, cn->name, cn->descriptor);
2011 :
2012 18 : if (m == NULL) {
2013 0 : exceptions_throw_internalerror("Enclosing method doesn't exist");
2014 0 : return NULL;
2015 : }
2016 :
2017 18 : return m;
2018 : }
2019 :
2020 :
2021 : /**
2022 : * Return the enclosing method as java.lang.reflect.Method object for
2023 : * the given class.
2024 : *
2025 : * @param c class to return the enclosing method for
2026 : *
2027 : * @return java.lang.reflect.Method object of the enclosing method
2028 : */
2029 : #if defined(ENABLE_JAVASE)
2030 12 : java_handle_t* class_get_enclosingmethod(classinfo *c)
2031 : {
2032 : methodinfo* m;
2033 :
2034 12 : m = class_get_enclosingmethod_raw(c);
2035 :
2036 12 : if (m == NULL)
2037 3 : return NULL;
2038 :
2039 : /* check for <init> */
2040 :
2041 9 : if (m->name == utf8::init)
2042 6 : return NULL;
2043 :
2044 : // Create a java.lang.reflect.Method object.
2045 :
2046 3 : java_lang_reflect_Method rm(m);
2047 :
2048 3 : return rm.get_handle();
2049 : }
2050 : #endif
2051 :
2052 :
2053 : /* class_get_interfaces ********************************************************
2054 :
2055 : Return an array of interfaces of the given class.
2056 :
2057 : *******************************************************************************/
2058 :
2059 94 : java_handle_objectarray_t* class_get_interfaces(classinfo *c)
2060 : {
2061 94 : if (!(c->state & CLASS_LINKED))
2062 0 : if (!link_class(c))
2063 0 : return NULL;
2064 :
2065 94 : ClassArray interfaces(c->interfacescount);
2066 :
2067 94 : if (interfaces.is_null())
2068 0 : return NULL;
2069 :
2070 118 : for (int32_t i = 0; i < c->interfacescount; i++) {
2071 24 : classinfo* ic = c->interfaces[i];
2072 :
2073 24 : interfaces.set_element(i, ic);
2074 : }
2075 :
2076 94 : return interfaces.get_handle();
2077 : }
2078 :
2079 :
2080 : /* class_get_annotations *******************************************************
2081 :
2082 : Get the unparsed declared annotations in a byte array
2083 : of the given class.
2084 :
2085 : IN:
2086 : c........the class of which the annotations should be returned
2087 :
2088 : RETURN VALUE:
2089 : The unparsed declared annotations in a byte array
2090 : (or NULL if there aren't any).
2091 :
2092 : *******************************************************************************/
2093 :
2094 778 : java_handle_bytearray_t *class_get_annotations(classinfo *c)
2095 : {
2096 : #if defined(ENABLE_ANNOTATIONS)
2097 : java_handle_t *annotations; /* unparsed annotations */
2098 :
2099 778 : LLNI_classinfo_field_get(c, annotations, annotations);
2100 :
2101 778 : return (java_handle_bytearray_t*) annotations;
2102 : #else
2103 : return NULL;
2104 : #endif
2105 : }
2106 :
2107 :
2108 : /* class_get_modifiers *********************************************************
2109 :
2110 : Get the modifier flags of the given class.
2111 :
2112 : IN:
2113 : c....the class of which the modifier flags should be returned
2114 : ignoreInnerClassesAttrib
2115 : RETURN VALUE:
2116 : modifier flags
2117 :
2118 : *******************************************************************************/
2119 :
2120 441 : int32_t class_get_modifiers(classinfo *c, bool ignoreInnerClassesAttrib)
2121 : {
2122 : /* default to flags of passed class */
2123 :
2124 441 : int32_t flags = c->flags;
2125 :
2126 : /* if requested we check if passed class is inner class */
2127 :
2128 441 : if (!ignoreInnerClassesAttrib && (c->innerclasscount != 0)) {
2129 : /* search for passed class as inner class */
2130 :
2131 94 : for (int i = 0; i < c->innerclasscount; i++) {
2132 78 : classref_or_classinfo inner = c->innerclass[i].inner_class;
2133 78 : classref_or_classinfo outer = c->innerclass[i].outer_class;
2134 :
2135 : /* Check if inner is a classref or a real class and get
2136 : the name of the structure */
2137 :
2138 78 : Utf8String innername = CLASSREF_OR_CLASSINFO_NAME(inner);
2139 :
2140 : /* innerclass is this class */
2141 :
2142 78 : if (innername == c->name) {
2143 : /* has the class actually an outer class? */
2144 :
2145 2 : if (outer.any)
2146 : /* return flags got from the outer class file */
2147 2 : flags = c->innerclass[i].flags;
2148 :
2149 2 : break;
2150 : }
2151 : }
2152 : }
2153 :
2154 : /* remove ACC_SUPER bit from flags */
2155 :
2156 441 : return flags & ~ACC_SUPER & ACC_CLASS_REFLECT_MASK;
2157 : }
2158 :
2159 :
2160 : /**
2161 : * Helper function for the function class_is_or_almost_initialized.
2162 : */
2163 103823 : bool class_initializing_thread_is_self(classinfo *c)
2164 : {
2165 103823 : threadobject *t = thread_get_current();
2166 103823 : return t == c->initializing_thread;
2167 : }
2168 :
2169 : /* class_get_signature *********************************************************
2170 :
2171 : Return the signature of the given class. For array and primitive
2172 : classes return NULL.
2173 :
2174 : *******************************************************************************/
2175 :
2176 : #if defined(ENABLE_JAVASE)
2177 0 : Utf8String class_get_signature(classinfo *c)
2178 : {
2179 : /* For array and primitive classes return NULL. */
2180 :
2181 0 : if (class_is_array(c) || class_is_primitive(c))
2182 0 : return NULL;
2183 :
2184 0 : return c->signature;
2185 : }
2186 : #endif
2187 :
2188 :
2189 : /* class_printflags ************************************************************
2190 :
2191 : Prints flags of a class.
2192 :
2193 : *******************************************************************************/
2194 :
2195 : #if !defined(NDEBUG)
2196 0 : void class_printflags(classinfo *c)
2197 : {
2198 0 : if (c == NULL) {
2199 0 : printf("NULL");
2200 0 : return;
2201 : }
2202 :
2203 0 : if (c->flags & ACC_PUBLIC) printf(" PUBLIC");
2204 0 : if (c->flags & ACC_PRIVATE) printf(" PRIVATE");
2205 0 : if (c->flags & ACC_PROTECTED) printf(" PROTECTED");
2206 0 : if (c->flags & ACC_STATIC) printf(" STATIC");
2207 0 : if (c->flags & ACC_FINAL) printf(" FINAL");
2208 0 : if (c->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
2209 0 : if (c->flags & ACC_VOLATILE) printf(" VOLATILE");
2210 0 : if (c->flags & ACC_TRANSIENT) printf(" TRANSIENT");
2211 0 : if (c->flags & ACC_NATIVE) printf(" NATIVE");
2212 0 : if (c->flags & ACC_INTERFACE) printf(" INTERFACE");
2213 0 : if (c->flags & ACC_ABSTRACT) printf(" ABSTRACT");
2214 : }
2215 : #endif
2216 :
2217 :
2218 : /* class_print *****************************************************************
2219 :
2220 : Prints classname plus flags.
2221 :
2222 : *******************************************************************************/
2223 :
2224 : #if !defined(NDEBUG)
2225 0 : void class_print(classinfo *c)
2226 : {
2227 0 : if (c == NULL) {
2228 0 : printf("NULL");
2229 0 : return;
2230 : }
2231 :
2232 0 : utf_display_printable_ascii(c->name);
2233 0 : class_printflags(c);
2234 : }
2235 : #endif
2236 :
2237 :
2238 : /* class_classref_print ********************************************************
2239 :
2240 : Prints classname plus referer class.
2241 :
2242 : *******************************************************************************/
2243 :
2244 : #if !defined(NDEBUG)
2245 0 : void class_classref_print(constant_classref *cr)
2246 : {
2247 0 : if (cr == NULL) {
2248 0 : printf("NULL");
2249 0 : return;
2250 : }
2251 :
2252 0 : utf_display_printable_ascii(cr->name);
2253 0 : printf("(ref.by ");
2254 0 : if (cr->referer)
2255 0 : class_print(cr->referer);
2256 : else
2257 0 : printf("NULL");
2258 0 : printf(")");
2259 : }
2260 : #endif
2261 :
2262 :
2263 : /* class_println ***************************************************************
2264 :
2265 : Prints classname plus flags and new line.
2266 :
2267 : *******************************************************************************/
2268 :
2269 : #if !defined(NDEBUG)
2270 0 : void class_println(classinfo *c)
2271 : {
2272 0 : class_print(c);
2273 0 : printf("\n");
2274 0 : }
2275 : #endif
2276 :
2277 :
2278 : /* class_classref_println ******************************************************
2279 :
2280 : Prints classname plus referer class and new line.
2281 :
2282 : *******************************************************************************/
2283 :
2284 : #if !defined(NDEBUG)
2285 0 : void class_classref_println(constant_classref *cr)
2286 : {
2287 0 : class_classref_print(cr);
2288 0 : printf("\n");
2289 0 : }
2290 : #endif
2291 :
2292 :
2293 : /* class_classref_or_classinfo_print *******************************************
2294 :
2295 : Prints classname plus referer class.
2296 :
2297 : *******************************************************************************/
2298 :
2299 : #if !defined(NDEBUG)
2300 0 : void class_classref_or_classinfo_print(classref_or_classinfo c)
2301 : {
2302 0 : if (c.any == NULL) {
2303 0 : printf("(classref_or_classinfo) NULL");
2304 0 : return;
2305 : }
2306 0 : if (c.is_classref())
2307 0 : class_classref_print(c.ref);
2308 : else
2309 0 : class_print(c.cls);
2310 : }
2311 : #endif
2312 :
2313 :
2314 : /* class_classref_or_classinfo_println *****************************************
2315 :
2316 : Prints classname plus referer class and a newline.
2317 :
2318 : *******************************************************************************/
2319 :
2320 : #if !defined(NDEBUG)
2321 0 : void class_classref_or_classinfo_println(classref_or_classinfo c)
2322 : {
2323 0 : class_classref_or_classinfo_print(c);
2324 0 : printf("\n");
2325 0 : }
2326 : #endif
2327 :
2328 :
2329 : /* class_showconstantpool ******************************************************
2330 :
2331 : Dump the constant pool of the given class to stdout.
2332 :
2333 : *******************************************************************************/
2334 :
2335 : #if !defined(NDEBUG)
2336 0 : void class_showconstantpool (classinfo *c)
2337 : {
2338 0 : printf ("---- dump of constant pool ----\n");
2339 :
2340 0 : for (int32_t i=0; i<c->cpcount; i++) {
2341 0 : printf ("#%u: ", i);
2342 :
2343 0 : if (void *e = c->cpinfos[i]) {
2344 0 : switch ((ConstantPoolTag) c->cptags[i]) {
2345 : case CONSTANT_Class:
2346 0 : printf ("Classreference -> ");
2347 0 : utf_display_printable_ascii ( ((constant_classref*)e) -> name );
2348 0 : break;
2349 : case CONSTANT_Fieldref:
2350 0 : printf ("Fieldref -> ");
2351 0 : field_fieldref_print((constant_FMIref *) e);
2352 0 : break;
2353 : case CONSTANT_Methodref:
2354 0 : printf ("Methodref -> ");
2355 0 : method_methodref_print((constant_FMIref *) e);
2356 0 : break;
2357 : case CONSTANT_InterfaceMethodref:
2358 0 : printf ("InterfaceMethod -> ");
2359 0 : method_methodref_print((constant_FMIref *) e);
2360 0 : break;
2361 : case CONSTANT_String:
2362 0 : printf ("String -> ");
2363 0 : utf_display_printable_ascii ((utf*) e);
2364 0 : break;
2365 : case CONSTANT_Integer:
2366 0 : printf ("Integer -> %d", *reinterpret_cast<int32_t*>(e));
2367 0 : break;
2368 : case CONSTANT_Float:
2369 0 : printf ("Float -> %f", *reinterpret_cast<float*>(e));
2370 0 : break;
2371 : case CONSTANT_Double:
2372 0 : printf ("Double -> %f", *reinterpret_cast<double*>(e));
2373 0 : break;
2374 : case CONSTANT_Long:
2375 0 : printf ("Long -> %" PRId64, *reinterpret_cast<int64_t*>(e));
2376 0 : break;
2377 : case CONSTANT_NameAndType:
2378 : {
2379 0 : constant_nameandtype *cnt = (constant_nameandtype *) e;
2380 0 : printf ("NameAndType: ");
2381 0 : utf_display_printable_ascii (cnt->name);
2382 0 : printf (" ");
2383 0 : utf_display_printable_ascii (cnt->descriptor);
2384 : }
2385 0 : break;
2386 : case CONSTANT_Utf8:
2387 0 : printf ("Utf8 -> ");
2388 0 : utf_display_printable_ascii ((utf*) e);
2389 0 : break;
2390 : case CONSTANT_MethodType: {
2391 0 : constant_MethodType *type = (constant_MethodType*) e;
2392 :
2393 0 : printf ("MethodType -> ");
2394 0 : utf_display_printable_ascii(type->descriptor);
2395 0 : break;
2396 : }
2397 : case CONSTANT_MethodHandle: {
2398 0 : constant_MethodHandle *handle = (constant_MethodHandle*) e;
2399 :
2400 0 : printf ("MethodHandle -> ");
2401 0 : utf_display_printable_ascii(handle->fmi->name);
2402 0 : utf_display_printable_ascii(handle->fmi->descriptor);
2403 0 : break;
2404 : }
2405 : case CONSTANT_InvokeDynamic: {
2406 0 : constant_InvokeDynamic* indy = (constant_InvokeDynamic*) e;
2407 :
2408 0 : printf ("InvokeDynamic -> ");
2409 0 : utf_display_printable_ascii(indy->name);
2410 0 : utf_display_printable_ascii(indy->descriptor);
2411 0 : printf(" [%u]", indy->bootstrap_method_index);
2412 0 : break;
2413 : }
2414 : default:
2415 0 : log_text("Invalid type of ConstantPool-Entry");
2416 0 : assert(0);
2417 : }
2418 : }
2419 :
2420 0 : printf ("\n");
2421 : }
2422 0 : }
2423 : #endif /* !defined(NDEBUG) */
2424 :
2425 :
2426 : /* class_showmethods ***********************************************************
2427 :
2428 : Dump info about the fields and methods of the given class to stdout.
2429 :
2430 : *******************************************************************************/
2431 :
2432 : #if !defined(NDEBUG)
2433 0 : void class_showmethods (classinfo *c)
2434 : {
2435 0 : printf("--------- Fields and Methods ----------------\n");
2436 0 : printf("Flags: ");
2437 0 : class_printflags(c);
2438 0 : printf("\n");
2439 :
2440 0 : printf("This: ");
2441 0 : utf_display_printable_ascii(c->name);
2442 0 : printf("\n");
2443 :
2444 0 : if (c->super) {
2445 0 : printf("Super: ");
2446 0 : utf_display_printable_ascii(c->super->name);
2447 0 : printf ("\n");
2448 : }
2449 :
2450 0 : printf("Index: %d\n", c->index);
2451 :
2452 0 : printf("Interfaces:\n");
2453 0 : for (int32_t i = 0; i < c->interfacescount; i++) {
2454 0 : printf(" ");
2455 0 : utf_display_printable_ascii(c->interfaces[i]->name);
2456 0 : printf (" (%d)\n", c->interfaces[i]->index);
2457 : }
2458 :
2459 0 : printf("Fields:\n");
2460 0 : for (int32_t i = 0; i < c->fieldscount; i++)
2461 0 : field_println(&(c->fields[i]));
2462 :
2463 0 : printf("Methods:\n");
2464 0 : for (int32_t i = 0; i < c->methodscount; i++) {
2465 0 : methodinfo *m = &(c->methods[i]);
2466 :
2467 0 : if (!(m->flags & ACC_STATIC))
2468 0 : printf("vftblindex: %d ", m->vftblindex);
2469 :
2470 0 : method_println(m);
2471 : }
2472 :
2473 0 : printf ("Virtual function table:\n");
2474 0 : for (int32_t i = 0; i < c->vftbl->vftbllength; i++)
2475 0 : printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]));
2476 0 : }
2477 : #endif /* !defined(NDEBUG) */
2478 :
2479 : namespace cacao {
2480 :
2481 0 : OStream& operator<<(OStream& os, const classinfo *c) {
2482 0 : if (c == NULL) {
2483 0 : os << "NULL";
2484 0 : return os;
2485 : }
2486 :
2487 0 : os << (Utf8String)c->name;
2488 : // print flags
2489 0 : if (c->flags & ACC_PUBLIC) os << " PUBLIC";
2490 0 : if (c->flags & ACC_PRIVATE) os << " PRIVATE";
2491 0 : if (c->flags & ACC_PROTECTED) os << " PROTECTED";
2492 0 : if (c->flags & ACC_STATIC) os << " STATIC";
2493 0 : if (c->flags & ACC_FINAL) os << " FINAL";
2494 0 : if (c->flags & ACC_SYNCHRONIZED) os << " SYNCHRONIZED";
2495 0 : if (c->flags & ACC_VOLATILE) os << " VOLATILE";
2496 0 : if (c->flags & ACC_TRANSIENT) os << " TRANSIENT";
2497 0 : if (c->flags & ACC_NATIVE) os << " NATIVE";
2498 0 : if (c->flags & ACC_INTERFACE) os << " INTERFACE";
2499 0 : if (c->flags & ACC_ABSTRACT) os << " ABSTRACT";
2500 :
2501 0 : return os;
2502 : }
2503 :
2504 : }
2505 :
2506 : /*
2507 : * These are local overrides for various environment variables in Emacs.
2508 : * Please do not remove this and leave it at the end of the file, where
2509 : * Emacs will automagically detect them.
2510 : * ---------------------------------------------------------------------
2511 : * Local variables:
2512 : * mode: c++
2513 : * indent-tabs-mode: t
2514 : * c-basic-offset: 4
2515 : * tab-width: 4
2516 : * End:
2517 : * vim:noexpandtab:sw=4:ts=4:
2518 : */
|