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