Line data Source code
1 : /* src/vm/method.cpp - method functions
2 :
3 : Copyright (C) 1996-2013
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 :
26 : #include "vm/method.hpp"
27 : #include "config.h" // for ENABLE_ANNOTATIONS, etc
28 :
29 : #include <cassert> // for assert
30 : #include <cstdio> // for printf
31 : #include <stdint.h> // for int32_t
32 :
33 : #include "mm/memory.hpp"
34 :
35 : #include "native/llni.hpp"
36 :
37 : #include "threads/mutex.hpp" // for Mutex
38 :
39 : #include "vm/annotation.hpp"
40 : #include "vm/array.hpp" // for ObjectArray, ClassArray
41 : #include "vm/breakpoint.hpp" // for BreakpointTable
42 : #include "vm/class.hpp" // for classinfo, etc
43 : #include "vm/descriptor.hpp"
44 : #include "vm/exceptions.hpp"
45 : #include "vm/global.hpp" // for java_handle_bytearray_t, etc
46 : #include "vm/globals.hpp"
47 : #include "vm/linker.hpp"
48 : #include "vm/loader.hpp" // for loader_skip_attribute_body, etc
49 : #include "vm/options.hpp" // for opt_debugcolor, opt_verify, etc
50 : #include "vm/references.hpp" // for classref_or_classinfo, etc
51 : #include "vm/resolve.hpp" // for resolve_class_from_typedesc, etc
52 : #include "vm/stackmap.hpp"
53 : #include "vm/statistics.hpp"
54 : #include "vm/suck.hpp" // for suck_u2, etc
55 : #include "vm/types.hpp" // for s4, u2, u1, u4
56 : #include "vm/utf8.hpp" // for Utf8String, etc
57 : #include "vm/vftbl.hpp" // for vftbl_t
58 : #include "vm/vm.hpp" // for vm_abort
59 :
60 : #include "vm/jit/builtin.hpp" // for builtintable_entry
61 : #include "vm/jit/code.hpp" // for code_free_code_of_method, etc
62 : #include "vm/jit/methodheader.hpp"
63 : #include "vm/jit/stubs.hpp" // for CompilerStub, NativeStub
64 :
65 : using namespace cacao;
66 :
67 :
68 : #if !defined(NDEBUG) && defined(ENABLE_INLINING)
69 : #define INLINELOG(code) do { if (opt_TraceInlining) { code } } while (0)
70 : #else
71 : #define INLINELOG(code)
72 : #endif
73 :
74 :
75 : STAT_REGISTER_VAR(int,count_all_methods,0,"all methods","Number of loaded Methods")
76 :
77 : STAT_DECLARE_GROUP(info_struct_stat)
78 : STAT_REGISTER_GROUP_VAR(int,size_lineinfo,0,"size lineinfo","lineinfo",info_struct_stat) // sizeof(lineinfo)?
79 :
80 : STAT_DECLARE_GROUP(memory_stat)
81 : STAT_REGISTER_SUM_SUBGROUP(table_stat,"info structs","info struct usage",memory_stat)
82 : STAT_REGISTER_GROUP_VAR(int,count_extable_len,0,"extable len","exception tables",table_stat)
83 : STAT_REGISTER_GROUP_VAR_EXTERN(int,size_linenumbertable,0,"size linenumbertable","size of linenumber tables",table_stat)
84 : STAT_REGISTER_GROUP_VAR_EXTERN(int,count_linenumbertable,0,"count linenumbertable","number of linenumber tables",table_stat)
85 : STAT_REGISTER_GROUP_VAR_EXTERN(int,size_patchref,0,"patchref","patcher references",table_stat)
86 :
87 : STAT_DECLARE_VAR(int,count_vmcode_len,0)
88 : /* global variables ***********************************************************/
89 :
90 : methodinfo *method_java_lang_reflect_Method_invoke;
91 :
92 :
93 : /* method_init *****************************************************************
94 :
95 : Initialize method subsystem.
96 :
97 : *******************************************************************************/
98 :
99 163 : void method_init(void)
100 : {
101 : #if defined(ENABLE_JAVASE)
102 : /* Sanity check. */
103 :
104 163 : if (class_java_lang_reflect_Method == NULL)
105 0 : vm_abort("method_init: class_java_lang_reflect_Method is NULL");
106 :
107 : /* Cache java.lang.reflect.Method.invoke() */
108 :
109 : method_java_lang_reflect_Method_invoke =
110 163 : class_findmethod(class_java_lang_reflect_Method, utf8::invoke, NULL);
111 :
112 163 : if (method_java_lang_reflect_Method_invoke == NULL)
113 0 : vm_abort("method_init: Could not resolve method java.lang.reflect.Method.invoke().");
114 : #endif
115 163 : }
116 :
117 :
118 : /* method_load *****************************************************************
119 :
120 : Loads a method from the class file and fills an existing methodinfo
121 : structure.
122 :
123 : method_info {
124 : u2 access_flags;
125 : u2 name_index;
126 : u2 descriptor_index;
127 : u2 attributes_count;
128 : attribute_info attributes[attribute_count];
129 : }
130 :
131 : attribute_info {
132 : u2 attribute_name_index;
133 : u4 attribute_length;
134 : u1 info[attribute_length];
135 : }
136 :
137 : LineNumberTable_attribute {
138 : u2 attribute_name_index;
139 : u4 attribute_length;
140 : u2 line_number_table_length;
141 : {
142 : u2 start_pc;
143 : u2 line_number;
144 : } line_number_table[line_number_table_length];
145 : }
146 :
147 : LocalVariableTable_attribute {
148 : u2 attribute_name_index;
149 : u4 attribute_length;
150 : u2 local_variable_table_length;
151 : {
152 : u2 start_pc;
153 : u2 length;
154 : u2 name_index;
155 : u2 descriptor_index;
156 : u2 index;
157 : } local_variable_table[local_variable_table_length];
158 : }
159 :
160 : *******************************************************************************/
161 :
162 469928 : bool method_load(ClassBuffer& cb, methodinfo *m, DescriptorPool& descpool)
163 : {
164 : int argcount;
165 : s4 i, j, k, l;
166 469928 : Utf8String u;
167 : u2 name_index;
168 : u2 descriptor_index;
169 : u2 attributes_count;
170 : u2 attribute_name_index;
171 469928 : Utf8String attribute_name;
172 : u2 code_attributes_count;
173 : u2 code_attribute_name_index;
174 469928 : Utf8String code_attribute_name;
175 :
176 : /* get classinfo */
177 :
178 469928 : classinfo *c = cb.get_class();
179 :
180 469928 : m->mutex = new Mutex();
181 :
182 : STATISTICS(count_all_methods++);
183 :
184 : /* all fields of m have been zeroed in load_class_from_classbuffer */
185 :
186 469928 : m->clazz = c;
187 :
188 469928 : if (!cb.check_size(2 + 2 + 2))
189 0 : return false;
190 :
191 : /* access flags */
192 :
193 469928 : m->flags = cb.read_u2();
194 :
195 : /* name */
196 :
197 469928 : name_index = cb.read_u2();
198 :
199 469928 : if (!(u = (utf*) class_getconstant(c, name_index, CONSTANT_Utf8)))
200 0 : return false;
201 :
202 469928 : m->name = u;
203 :
204 : /* descriptor */
205 :
206 469928 : descriptor_index = cb.read_u2();
207 :
208 469928 : if (!(u = (utf*) class_getconstant(c, descriptor_index, CONSTANT_Utf8)))
209 0 : return false;
210 :
211 469928 : m->descriptor = u;
212 :
213 469928 : if ((argcount = descpool.add_method(u)) == -1)
214 0 : return false;
215 :
216 : #ifdef ENABLE_VERIFIER
217 469928 : if (opt_verify) {
218 469928 : if (!Utf8String(m->name).is_valid_name()) {
219 0 : exceptions_throw_classformaterror(c, "Method with invalid name");
220 0 : return false;
221 : }
222 :
223 469928 : if (m->name[0] == '<' &&
224 : m->name != utf8::init && m->name != utf8::clinit) {
225 0 : exceptions_throw_classformaterror(c, "Method with invalid special name");
226 0 : return false;
227 : }
228 : }
229 : #endif /* ENABLE_VERIFIER */
230 :
231 : /* Ignore flags for class initializer according to section 4.6
232 : of "The Java Virtual Machine Specification, 2nd Edition" (see PR125). */
233 :
234 469928 : if (m->name == utf8::clinit) {
235 9149 : m->flags &= ACC_STRICT;
236 9149 : m->flags |= ACC_STATIC;
237 : }
238 :
239 469928 : if (!(m->flags & ACC_STATIC))
240 361561 : argcount++; /* count the 'this' argument */
241 :
242 : #ifdef ENABLE_VERIFIER
243 469928 : if (opt_verify) {
244 469928 : if (argcount > 255) {
245 0 : exceptions_throw_classformaterror(c, "Too many arguments in signature");
246 0 : return false;
247 : }
248 :
249 : /* check flag consistency */
250 469928 : if (m->name != utf8::clinit) {
251 460779 : i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
252 :
253 460779 : if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) {
254 : exceptions_throw_classformaterror(c,
255 : "Illegal method modifiers: 0x%X",
256 0 : m->flags);
257 0 : return false;
258 : }
259 :
260 460779 : if (m->flags & ACC_ABSTRACT) {
261 41898 : if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
262 : ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
263 : exceptions_throw_classformaterror(c,
264 : "Illegal method modifiers: 0x%X",
265 0 : m->flags);
266 0 : return false;
267 : }
268 : }
269 :
270 460779 : if (c->flags & ACC_INTERFACE) {
271 24254 : if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) {
272 : exceptions_throw_classformaterror(c,
273 : "Illegal method modifiers: 0x%X",
274 0 : m->flags);
275 0 : return false;
276 : }
277 : }
278 :
279 460779 : if (m->name == utf8::init) {
280 50954 : if (m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
281 : ACC_NATIVE | ACC_ABSTRACT)) {
282 0 : exceptions_throw_classformaterror(c, "Instance initialization method has invalid flags set");
283 0 : return false;
284 : }
285 : }
286 : }
287 : }
288 : #endif /* ENABLE_VERIFIER */
289 :
290 : /* mark the method as monomorphic until further notice */
291 :
292 469928 : m->flags |= ACC_METHOD_MONOMORPHIC;
293 :
294 : /* non-abstract methods have an implementation in this class */
295 :
296 469928 : if (!(m->flags & ACC_ABSTRACT))
297 428030 : m->flags |= ACC_METHOD_IMPLEMENTED;
298 :
299 469928 : if (!cb.check_size(2))
300 0 : return false;
301 :
302 : /* attributes count */
303 :
304 469928 : attributes_count = cb.read_u2();
305 :
306 997905 : for (i = 0; i < attributes_count; i++) {
307 527977 : if (!cb.check_size(2))
308 0 : return false;
309 :
310 : /* attribute name index */
311 :
312 527977 : attribute_name_index = cb.read_u2();
313 :
314 : attribute_name =
315 527977 : (utf*) class_getconstant(c, attribute_name_index, CONSTANT_Utf8);
316 :
317 527977 : if (attribute_name == NULL)
318 0 : return false;
319 :
320 527977 : if (attribute_name == utf8::Code) {
321 : /* Code */
322 :
323 398374 : if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
324 0 : exceptions_throw_classformaterror(c, "Code attribute in native or abstract methods");
325 0 : return false;
326 : }
327 :
328 398374 : if (m->jcode) {
329 0 : exceptions_throw_classformaterror(c, "Multiple Code attributes");
330 0 : return false;
331 : }
332 :
333 398374 : if (!cb.check_size(4 + 2 + 2))
334 0 : return false;
335 :
336 398374 : cb.read_u4();
337 398374 : m->maxstack = cb.read_u2();
338 398374 : m->maxlocals = cb.read_u2();
339 :
340 398374 : if (m->maxlocals < argcount) {
341 0 : exceptions_throw_classformaterror(c, "Arguments can't fit into locals");
342 0 : return false;
343 : }
344 :
345 398374 : if (!cb.check_size(4))
346 0 : return false;
347 :
348 398374 : m->jcodelength = cb.read_u4();
349 :
350 398374 : if (m->jcodelength == 0) {
351 0 : exceptions_throw_classformaterror(c, "Code of a method has length 0");
352 0 : return false;
353 : }
354 :
355 398374 : if (m->jcodelength > 65535) {
356 0 : exceptions_throw_classformaterror(c, "Code of a method longer than 65535 bytes");
357 0 : return false;
358 : }
359 :
360 398374 : if (!cb.check_size(m->jcodelength))
361 0 : return false;
362 :
363 398374 : m->jcode = MNEW(u1, m->jcodelength);
364 398374 : cb.read_nbytes(m->jcode, m->jcodelength);
365 :
366 398374 : if (!cb.check_size(2))
367 0 : return false;
368 :
369 398374 : m->rawexceptiontablelength = cb.read_u2();
370 398374 : if (!cb.check_size((2 + 2 + 2 + 2) * m->rawexceptiontablelength))
371 0 : return false;
372 :
373 398374 : m->rawexceptiontable = MNEW(raw_exception_entry, m->rawexceptiontablelength);
374 :
375 : STATISTICS(count_vmcode_len += m->jcodelength + 18);
376 : STATISTICS(count_extable_len +=
377 : m->rawexceptiontablelength * sizeof(raw_exception_entry));
378 :
379 441557 : for (j = 0; j < m->rawexceptiontablelength; j++) {
380 : u4 idx;
381 43183 : m->rawexceptiontable[j].startpc = cb.read_u2();
382 43183 : m->rawexceptiontable[j].endpc = cb.read_u2();
383 43183 : m->rawexceptiontable[j].handlerpc = cb.read_u2();
384 :
385 43183 : idx = cb.read_u2();
386 :
387 43183 : if (!idx) {
388 20709 : m->rawexceptiontable[j].catchtype.any = NULL;
389 : }
390 : else {
391 : /* the classref is created later */
392 22474 : if (!(m->rawexceptiontable[j].catchtype.any =
393 : (utf *) class_getconstant(c, idx, CONSTANT_ClassName)))
394 0 : return false;
395 : }
396 : }
397 :
398 398374 : if (!cb.check_size(2))
399 0 : return false;
400 :
401 : /* code attributes count */
402 :
403 398374 : code_attributes_count = cb.read_u2();
404 :
405 946103 : for (k = 0; k < code_attributes_count; k++) {
406 547729 : if (!cb.check_size(2))
407 0 : return false;
408 :
409 : /* code attribute name index */
410 :
411 547729 : code_attribute_name_index = cb.read_u2();
412 :
413 : code_attribute_name =
414 547729 : (utf*) class_getconstant(c, code_attribute_name_index, CONSTANT_Utf8);
415 :
416 547729 : if (code_attribute_name == NULL)
417 0 : return false;
418 :
419 : /* check which code attribute */
420 :
421 547729 : if (code_attribute_name == utf8::LineNumberTable) {
422 : /* LineNumberTable */
423 :
424 397933 : if (!cb.check_size(4 + 2))
425 0 : return false;
426 :
427 : /* attribute length */
428 :
429 397933 : (void) cb.read_u4();
430 :
431 : /* line number table length */
432 :
433 397933 : m->linenumbercount = cb.read_u2();
434 :
435 397933 : if (!cb.check_size((2 + 2) * m->linenumbercount))
436 0 : return false;
437 :
438 397933 : m->linenumbers = MNEW(lineinfo, m->linenumbercount);
439 :
440 : STATISTICS(size_lineinfo += sizeof(lineinfo) * m->linenumbercount);
441 :
442 2344518 : for (l = 0; l < m->linenumbercount; l++) {
443 1946585 : m->linenumbers[l].start_pc = cb.read_u2();
444 1946585 : m->linenumbers[l].line_number = cb.read_u2();
445 : }
446 : }
447 : #if defined(ENABLE_JAVASE)
448 149796 : else if (code_attribute_name == utf8::StackMapTable) {
449 : /* StackTableMap */
450 :
451 148188 : if (!stackmap_load_attribute_stackmaptable(cb, m))
452 0 : return false;
453 : }
454 : # if defined(ENABLE_JVMTI)
455 : else if (code_attribute_name == utf8::LocalVariableTable) {
456 : /* LocalVariableTable */
457 :
458 : if (m->localvars != NULL) {
459 : exceptions_throw_classformaterror(c, "Multiple LocalVariableTable attributes");
460 : return false;
461 : }
462 :
463 : if (!cb.check_size(4 + 2))
464 : return false;
465 :
466 : // Attribute length.
467 : (void) cb.read_u4();
468 :
469 : m->localvarcount = cb.read_u2();
470 :
471 : if (!cb.check_size(10 * m->localvarcount))
472 : return false;
473 :
474 : m->localvars = MNEW(localvarinfo, m->localvarcount);
475 :
476 : for (l = 0; l < m->localvarcount; l++) {
477 : m->localvars[l].start_pc = cb.read_u2();
478 : m->localvars[l].length = cb.read_u2();
479 :
480 : uint16_t name_index = cb.read_u2();
481 : if (!(m->localvars[l].name = (utf*) class_getconstant(c, name_index, CONSTANT_Utf8)))
482 : return false;
483 :
484 : uint16_t descriptor_index = cb.read_u2();
485 : if (!(m->localvars[l].descriptor = (utf*) class_getconstant(c, descriptor_index, CONSTANT_Utf8)))
486 : return false;
487 :
488 : m->localvars[l].index = cb.read_u2();
489 :
490 : // XXX Check if index is in range.
491 : // XXX Check if index already taken.
492 : }
493 : }
494 : # endif /* defined(ENABLE_JVMTI) */
495 : #endif /* defined(ENABLE_JAVASE) */
496 : else {
497 : /* unknown code attribute */
498 :
499 1608 : if (!loader_skip_attribute_body(cb))
500 0 : return false;
501 : }
502 : }
503 : }
504 129603 : else if (attribute_name == utf8::Exceptions) {
505 : /* Exceptions */
506 :
507 57861 : if (m->thrownexceptions != NULL) {
508 0 : exceptions_throw_classformaterror(c, "Multiple Exceptions attributes");
509 0 : return false;
510 : }
511 :
512 57861 : if (!cb.check_size(4 + 2))
513 0 : return false;
514 :
515 : /* attribute length */
516 :
517 57861 : (void) cb.read_u4();
518 :
519 57861 : m->thrownexceptionscount = cb.read_u2();
520 :
521 57861 : if (!cb.check_size(2 * m->thrownexceptionscount))
522 0 : return false;
523 :
524 57861 : m->thrownexceptions = MNEW(classref_or_classinfo, m->thrownexceptionscount);
525 :
526 120425 : for (j = 0; j < m->thrownexceptionscount; j++) {
527 : /* the classref is created later */
528 62564 : if (!((m->thrownexceptions)[j].any =
529 : (utf*) class_getconstant(c, cb.read_u2(), CONSTANT_ClassName)))
530 0 : return false;
531 : }
532 : }
533 : #if defined(ENABLE_JAVASE)
534 71742 : else if (attribute_name == utf8::Signature) {
535 : /* Signature */
536 :
537 : // TODO: change methodinfo.signature to Utf8String
538 : // and use it directly
539 :
540 66076 : Utf8String signature = m->signature;
541 :
542 66076 : if (!loader_load_attribute_signature(cb, signature)) {
543 0 : return false;
544 : }
545 :
546 66076 : m->signature = signature;
547 : }
548 :
549 : # if defined(ENABLE_ANNOTATIONS)
550 5666 : else if (attribute_name == utf8::RuntimeVisibleAnnotations) {
551 : /* RuntimeVisibleAnnotations */
552 236 : if (!annotation_load_method_attribute_runtimevisibleannotations(cb, m))
553 0 : return false;
554 : }
555 5430 : else if (attribute_name == utf8::RuntimeInvisibleAnnotations) {
556 : /* RuntimeInvisibleAnnotations */
557 0 : if (!annotation_load_method_attribute_runtimeinvisibleannotations(cb, m))
558 0 : return false;
559 : }
560 5430 : else if (attribute_name == utf8::RuntimeVisibleParameterAnnotations) {
561 : /* RuntimeVisibleParameterAnnotations */
562 2 : if (!annotation_load_method_attribute_runtimevisibleparameterannotations(cb, m))
563 0 : return false;
564 : }
565 5428 : else if (attribute_name == utf8::RuntimeInvisibleParameterAnnotations) {
566 : /* RuntimeInvisibleParameterAnnotations */
567 0 : if (!annotation_load_method_attribute_runtimeinvisibleparameterannotations(cb, m))
568 0 : return false;
569 : }
570 5428 : else if (attribute_name == utf8::AnnotationDefault) {
571 : /* AnnotationDefault */
572 31 : if (!annotation_load_method_attribute_annotationdefault(cb, m))
573 0 : return false;
574 : }
575 : # endif
576 : #endif
577 : else {
578 : /* unknown attribute */
579 :
580 5397 : if (!loader_skip_attribute_body(cb))
581 0 : return false;
582 : }
583 : }
584 :
585 469928 : if ((m->jcode == NULL) && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
586 0 : exceptions_throw_classformaterror(c, "Missing Code attribute");
587 0 : return false;
588 : }
589 :
590 : #if defined(ENABLE_REPLACEMENT)
591 : /* initialize the hit countdown field */
592 :
593 : m->hitcountdown = METHOD_INITIAL_HIT_COUNTDOWN;
594 : #endif
595 :
596 : /* everything was ok */
597 :
598 469928 : return true;
599 : }
600 :
601 :
602 : /* method_free *****************************************************************
603 :
604 : Frees all memory that was allocated for this method.
605 :
606 : *******************************************************************************/
607 :
608 2 : void method_free(methodinfo *m)
609 : {
610 2 : if (m->mutex)
611 2 : delete m->mutex;
612 :
613 2 : if (m->jcode)
614 2 : MFREE(m->jcode, u1, m->jcodelength);
615 :
616 2 : if (m->rawexceptiontable)
617 0 : MFREE(m->rawexceptiontable, raw_exception_entry, m->rawexceptiontablelength);
618 :
619 2 : code_free_code_of_method(m);
620 :
621 2 : if (m->stubroutine) {
622 0 : if (m->flags & ACC_NATIVE) {
623 0 : NativeStub::remove(m->stubroutine);
624 : }
625 : else {
626 0 : CompilerStub::remove(m->stubroutine);
627 : }
628 : }
629 :
630 2 : if (m->breakpoints)
631 0 : delete m->breakpoints;
632 2 : }
633 :
634 :
635 : /* method_canoverwrite *********************************************************
636 :
637 : Check if m and old are identical with respect to type and
638 : name. This means that old can be overwritten with m.
639 :
640 : *******************************************************************************/
641 :
642 9956447 : bool method_canoverwrite(methodinfo *m, methodinfo *old)
643 : {
644 9956447 : if (m->name != old->name)
645 9431903 : return false;
646 :
647 524544 : if (m->descriptor != old->descriptor)
648 229579 : return false;
649 :
650 294965 : if (m->flags & ACC_STATIC)
651 0 : return false;
652 :
653 294965 : return true;
654 : }
655 :
656 :
657 : /* method_new_builtin **********************************************************
658 :
659 : Creates a minimal methodinfo structure for builtins. This comes handy
660 : when dealing with builtin stubs or stacktraces.
661 :
662 : *******************************************************************************/
663 :
664 2282 : methodinfo *method_new_builtin(builtintable_entry *bte)
665 : {
666 : methodinfo *m;
667 :
668 : /* allocate the methodinfo structure */
669 :
670 2282 : m = NEW(methodinfo);
671 :
672 : /* initialize methodinfo structure */
673 :
674 2282 : MZERO(m, methodinfo, 1);
675 :
676 2282 : m->mutex = new Mutex();
677 2282 : m->flags = ACC_METHOD_BUILTIN;
678 2282 : m->parseddesc = bte->md;
679 2282 : m->name = bte->name;
680 2282 : m->descriptor = bte->descriptor;
681 :
682 : /* return the newly created methodinfo */
683 :
684 2282 : return m;
685 : }
686 :
687 :
688 : /* method_vftbl_lookup *********************************************************
689 :
690 : Does a method lookup in the passed virtual function table. This
691 : function does exactly the same thing as JIT, but additionally
692 : relies on the fact, that the methodinfo pointer is at the first
693 : data segment slot (even for compiler stubs).
694 :
695 : *******************************************************************************/
696 :
697 665092 : methodinfo *method_vftbl_lookup(vftbl_t *vftbl, methodinfo* m)
698 : {
699 : methodptr mptr;
700 : methodptr *pmptr;
701 : methodinfo *resm; /* pointer to new resolved method */
702 :
703 : /* If the method is not an instance method, just return it. */
704 :
705 665092 : if (m->flags & ACC_STATIC)
706 0 : return m;
707 :
708 665092 : assert(vftbl);
709 :
710 : /* Get the method from the virtual function table. Is this an
711 : interface method? */
712 :
713 665092 : if (m->clazz->flags & ACC_INTERFACE) {
714 0 : pmptr = vftbl->interfacetable[-(m->clazz->index)];
715 0 : mptr = pmptr[(m - m->clazz->methods)];
716 : }
717 : else {
718 665092 : mptr = vftbl->table[m->vftblindex];
719 : }
720 :
721 : /* and now get the codeinfo pointer from the first data segment slot */
722 :
723 665092 : resm = code_get_methodinfo_for_pv(mptr);
724 :
725 665092 : return resm;
726 : }
727 :
728 :
729 : /* method_get_parametercount **************************************************
730 :
731 : Use the descriptor of a method to determine the number of parameters
732 : of the method. The this pointer of non-static methods is not counted.
733 :
734 : IN:
735 : m........the method of which the parameters should be counted
736 :
737 : RETURN VALUE:
738 : The parameter count.
739 :
740 : *******************************************************************************/
741 :
742 12 : int32_t method_get_parametercount(methodinfo *m)
743 : {
744 : methoddesc *md; /* method descriptor of m */
745 12 : int32_t paramcount = 0; /* the parameter count of m */
746 :
747 12 : md = m->parseddesc;
748 :
749 : /* is the descriptor fully parsed? */
750 :
751 12 : md->params_from_paramtypes(m->flags);
752 :
753 12 : paramcount = md->paramcount;
754 :
755 : /* skip `this' pointer */
756 :
757 12 : if (!(m->flags & ACC_STATIC)) {
758 9 : --paramcount;
759 : }
760 :
761 12 : return paramcount;
762 : }
763 :
764 :
765 : /* method_get_parametertypearray ***********************************************
766 :
767 : Use the descriptor of a method to generate a java.lang.Class array
768 : which contains the classes of the parametertypes of the method.
769 :
770 : This function is called by java.lang.reflect.{Constructor,Method}.
771 :
772 : *******************************************************************************/
773 :
774 1727 : java_handle_objectarray_t *method_get_parametertypearray(methodinfo *m)
775 : {
776 : methoddesc* md;
777 : typedesc* paramtypes;
778 : int32_t paramcount;
779 : int32_t i;
780 : classinfo* c;
781 :
782 1727 : md = m->parseddesc;
783 :
784 : /* is the descriptor fully parsed? */
785 :
786 1727 : md->params_from_paramtypes(m->flags);
787 :
788 1727 : paramtypes = md->paramtypes;
789 1727 : paramcount = md->paramcount;
790 :
791 : /* skip `this' pointer */
792 :
793 1727 : if (!(m->flags & ACC_STATIC)) {
794 1686 : paramtypes++;
795 1686 : paramcount--;
796 : }
797 :
798 : /* create class-array */
799 :
800 1727 : ClassArray ca(paramcount);
801 :
802 1727 : if (ca.is_null())
803 0 : return NULL;
804 :
805 : /* get classes */
806 :
807 2284 : for (i = 0; i < paramcount; i++) {
808 557 : if (!resolve_class_from_typedesc(¶mtypes[i], true, false, &c))
809 0 : return NULL;
810 :
811 557 : ca.set_element(i, c);
812 : }
813 :
814 1727 : return ca.get_handle();
815 : }
816 :
817 :
818 : /* method_get_exceptionarray ***************************************************
819 :
820 : Get the exceptions which can be thrown by a method.
821 :
822 : *******************************************************************************/
823 :
824 74 : java_handle_objectarray_t *method_get_exceptionarray(methodinfo *m)
825 : {
826 : classinfo* c;
827 : s4 i;
828 :
829 : /* create class-array */
830 :
831 74 : ClassArray ca(m->thrownexceptionscount);
832 :
833 74 : if (ca.is_null())
834 0 : return NULL;
835 :
836 : /* iterate over all exceptions and store the class in the array */
837 :
838 74 : for (i = 0; i < m->thrownexceptionscount; i++) {
839 0 : c = resolve_classref_or_classinfo_eager(m->thrownexceptions[i], true);
840 :
841 0 : if (c == NULL)
842 0 : return NULL;
843 :
844 0 : ca.set_element(i, c);
845 : }
846 :
847 74 : return ca.get_handle();
848 : }
849 :
850 :
851 : /* method_returntype_get *******************************************************
852 :
853 : Get the return type of the method.
854 :
855 : *******************************************************************************/
856 :
857 987 : classinfo *method_returntype_get(methodinfo *m)
858 : {
859 : typedesc *td;
860 : classinfo *c;
861 :
862 987 : td = &(m->parseddesc->returntype);
863 :
864 987 : if (!resolve_class_from_typedesc(td, true, false, &c))
865 0 : return NULL;
866 :
867 987 : return c;
868 : }
869 :
870 :
871 : /* method_count_implementations ************************************************
872 :
873 : Count the implementations of a method in a class cone (a class and all its
874 : subclasses.)
875 :
876 : IN:
877 : m................the method to count
878 : c................class at which to start the counting (this class and
879 : all its subclasses will be searched)
880 :
881 : OUT:
882 : *found...........if found != NULL, *found receives the method
883 : implementation that was found. This value is only
884 : meaningful if the return value is 1.
885 :
886 : RETURN VALUE:
887 : the number of implementations found
888 :
889 : *******************************************************************************/
890 :
891 0 : s4 method_count_implementations(methodinfo *m, classinfo *c, methodinfo **found)
892 : {
893 : s4 count;
894 : methodinfo *mp;
895 : methodinfo *mend;
896 : classinfo *child;
897 :
898 0 : count = 0;
899 :
900 0 : mp = c->methods;
901 0 : mend = mp + c->methodscount;
902 :
903 0 : for (; mp < mend; ++mp) {
904 0 : if (method_canoverwrite(mp, m)) {
905 0 : if (found)
906 0 : *found = mp;
907 0 : count++;
908 0 : break;
909 : }
910 : }
911 :
912 0 : for (child = c->sub; child != NULL; child = child->nextsub) {
913 0 : count += method_count_implementations(m, child, found);
914 : }
915 :
916 0 : return count;
917 : }
918 :
919 :
920 : /* method_get_annotations ******************************************************
921 :
922 : Get a methods' unparsed annotations in a byte array.
923 :
924 : IN:
925 : m........the method of which the annotations should be returned
926 :
927 : RETURN VALUE:
928 : The unparsed annotations in a byte array (or NULL if there aren't any).
929 :
930 : *******************************************************************************/
931 :
932 8509 : java_handle_bytearray_t *method_get_annotations(methodinfo *m)
933 : {
934 : #if defined(ENABLE_ANNOTATIONS)
935 : classinfo *c; /* methods' declaring class */
936 : int slot; /* methods' slot */
937 : java_handle_t *method_annotations; /* all methods' unparsed annotations */
938 : /* of the declaring class */
939 :
940 8509 : c = m->clazz;
941 8509 : slot = m - c->methods;
942 :
943 8509 : LLNI_classinfo_field_get(c, method_annotations, method_annotations);
944 :
945 8509 : ObjectArray oa((java_handle_objectarray_t*) method_annotations);
946 :
947 : /* the method_annotations array might be shorter then the method
948 : * count if the methods above a certain index have no annotations.
949 : */
950 8509 : if (method_annotations != NULL && oa.get_length() > slot) {
951 305 : return (java_handle_bytearray_t*) oa.get_element(slot);
952 : } else {
953 8204 : return NULL;
954 0 : }
955 : #else
956 : return NULL;
957 : #endif
958 : }
959 :
960 :
961 : /* method_get_parameterannotations ********************************************
962 :
963 : Get a methods' unparsed parameter annotations in an array of byte
964 : arrays.
965 :
966 : IN:
967 : m........the method of which the parameter annotations should be
968 : returned
969 :
970 : RETURN VALUE:
971 : The unparsed parameter annotations in a byte array (or NULL if
972 : there aren't any).
973 :
974 : *******************************************************************************/
975 :
976 8509 : java_handle_bytearray_t *method_get_parameterannotations(methodinfo *m)
977 : {
978 : #if defined(ENABLE_ANNOTATIONS)
979 : classinfo *c; /* methods' declaring class */
980 : int slot; /* methods' slot */
981 : java_handle_t *method_parameterannotations; /* all methods' unparsed */
982 : /* parameter annotations of */
983 : /* the declaring class */
984 :
985 8509 : c = m->clazz;
986 8509 : slot = m - c->methods;
987 :
988 8509 : LLNI_classinfo_field_get(
989 : c, method_parameterannotations, method_parameterannotations);
990 :
991 8509 : ObjectArray oa((java_handle_objectarray_t*) method_parameterannotations);
992 :
993 : /* the method_annotations array might be shorter then the method
994 : * count if the methods above a certain index have no annotations.
995 : */
996 8509 : if (method_parameterannotations != NULL && oa.get_length() > slot) {
997 9 : return (java_handle_bytearray_t*) oa.get_element(slot);
998 : } else {
999 8500 : return NULL;
1000 0 : }
1001 : #else
1002 : return NULL;
1003 : #endif
1004 : }
1005 :
1006 :
1007 : /* method_get_annotationdefault ***********************************************
1008 :
1009 : Get a methods' unparsed annotation default value in a byte array.
1010 :
1011 : IN:
1012 : m........the method of which the annotation default value should be
1013 : returned
1014 :
1015 : RETURN VALUE:
1016 : The unparsed annotation default value in a byte array (or NULL if
1017 : there isn't one).
1018 :
1019 : *******************************************************************************/
1020 :
1021 7933 : java_handle_bytearray_t *method_get_annotationdefault(methodinfo *m)
1022 : {
1023 : #if defined(ENABLE_ANNOTATIONS)
1024 : classinfo *c; /* methods' declaring class */
1025 : int slot; /* methods' slot */
1026 : java_handle_t *method_annotationdefaults; /* all methods' unparsed */
1027 : /* annotation default values of */
1028 : /* the declaring class */
1029 :
1030 7933 : c = m->clazz;
1031 7933 : slot = m - c->methods;
1032 :
1033 7933 : LLNI_classinfo_field_get(
1034 : c, method_annotationdefaults, method_annotationdefaults);
1035 :
1036 7933 : ObjectArray oa((java_handle_objectarray_t*) method_annotationdefaults);
1037 :
1038 : /* the method_annotations array might be shorter then the method
1039 : * count if the methods above a certain index have no annotations.
1040 : */
1041 7933 : if (method_annotationdefaults != NULL && oa.get_length() > slot) {
1042 1696 : return (java_handle_bytearray_t*) oa.get_element(slot);
1043 : } else {
1044 6237 : return NULL;
1045 0 : }
1046 : #else
1047 : return NULL;
1048 : #endif
1049 : }
1050 :
1051 :
1052 : /* method_add_to_worklist ******************************************************
1053 :
1054 : Add the method to the given worklist. If the method already occurs in
1055 : the worklist, the worklist remains unchanged.
1056 :
1057 : *******************************************************************************/
1058 :
1059 0 : static void method_add_to_worklist(methodinfo *m, method_worklist **wl)
1060 : {
1061 : method_worklist *wi;
1062 :
1063 0 : for (wi = *wl; wi != NULL; wi = wi->next)
1064 0 : if (wi->m == m)
1065 0 : return;
1066 :
1067 0 : wi = NEW(method_worklist);
1068 0 : wi->next = *wl;
1069 0 : wi->m = m;
1070 :
1071 0 : *wl = wi;
1072 : }
1073 :
1074 :
1075 : /* method_add_assumption_monomorphic *******************************************
1076 :
1077 : Record the assumption that the method is monomorphic.
1078 :
1079 : IN:
1080 : m.................the method
1081 : caller............the caller making the assumption
1082 :
1083 : *******************************************************************************/
1084 :
1085 0 : void method_add_assumption_monomorphic(methodinfo *m, methodinfo *caller)
1086 : {
1087 : method_assumption *as;
1088 :
1089 : /* XXX LOCKING FOR THIS FUNCTION? */
1090 :
1091 : /* check if we already have registered this assumption */
1092 :
1093 0 : for (as = m->assumptions; as != NULL; as = as->next) {
1094 0 : if (as->context == caller)
1095 0 : return;
1096 : }
1097 :
1098 : /* register the assumption */
1099 :
1100 0 : as = NEW(method_assumption);
1101 0 : as->next = m->assumptions;
1102 0 : as->context = caller;
1103 :
1104 0 : m->assumptions = as;
1105 : }
1106 :
1107 : /* method_break_assumption_monomorphic *****************************************
1108 :
1109 : Break the assumption that this method is monomorphic. All callers that
1110 : have registered this assumption are added to the worklist.
1111 :
1112 : IN:
1113 : m.................the method
1114 : wl................worklist where to add invalidated callers
1115 :
1116 : *******************************************************************************/
1117 :
1118 76646 : void method_break_assumption_monomorphic(methodinfo *m, method_worklist **wl)
1119 : {
1120 : method_assumption *as;
1121 :
1122 : /* XXX LOCKING FOR THIS FUNCTION? */
1123 :
1124 76646 : for (as = m->assumptions; as != NULL; as = as->next) {
1125 : INLINELOG(
1126 : printf("ASSUMPTION BROKEN (monomorphism): ");
1127 : method_print(m);
1128 : printf(" in ");
1129 : method_println(as->context);
1130 : );
1131 :
1132 0 : method_add_to_worklist(as->context, wl);
1133 :
1134 : #if defined(ENABLE_TLH) && 0
1135 : /* XXX hack */
1136 : method_assumption *as2;
1137 : as2 = m->assumptions;
1138 : m->assumptions = NULL;
1139 : method_break_assumption_monomorphic(as->context, wl);
1140 : /*
1141 : assert(m->assumptions == NULL);
1142 : m->assumptions = as2;*/
1143 : #endif
1144 :
1145 : }
1146 76646 : }
1147 :
1148 : /* method_printflags ***********************************************************
1149 :
1150 : Prints the flags of a method to stdout like.
1151 :
1152 : *******************************************************************************/
1153 :
1154 : #if !defined(NDEBUG)
1155 0 : void method_printflags(methodinfo *m)
1156 : {
1157 0 : if (m == NULL) {
1158 0 : printf("NULL");
1159 0 : return;
1160 : }
1161 :
1162 0 : if (m->flags & ACC_PUBLIC) printf(" PUBLIC");
1163 0 : if (m->flags & ACC_PRIVATE) printf(" PRIVATE");
1164 0 : if (m->flags & ACC_PROTECTED) printf(" PROTECTED");
1165 0 : if (m->flags & ACC_STATIC) printf(" STATIC");
1166 0 : if (m->flags & ACC_FINAL) printf(" FINAL");
1167 0 : if (m->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
1168 0 : if (m->flags & ACC_VOLATILE) printf(" VOLATILE");
1169 0 : if (m->flags & ACC_TRANSIENT) printf(" TRANSIENT");
1170 0 : if (m->flags & ACC_NATIVE) printf(" NATIVE");
1171 0 : if (m->flags & ACC_INTERFACE) printf(" INTERFACE");
1172 0 : if (m->flags & ACC_ABSTRACT) printf(" ABSTRACT");
1173 0 : if (m->flags & ACC_METHOD_BUILTIN) printf(" (builtin)");
1174 0 : if (m->flags & ACC_METHOD_MONOMORPHIC) printf(" (mono)");
1175 0 : if (m->flags & ACC_METHOD_IMPLEMENTED) printf(" (impl)");
1176 : }
1177 : #endif /* !defined(NDEBUG) */
1178 :
1179 :
1180 : /* method_print ****************************************************************
1181 :
1182 : Prints a method to stdout like:
1183 :
1184 : java.lang.Object.<init>()V
1185 :
1186 : *******************************************************************************/
1187 :
1188 : #if !defined(NDEBUG)
1189 0 : void method_print(methodinfo *m)
1190 : {
1191 0 : if (m == NULL) {
1192 0 : printf("NULL");
1193 0 : return;
1194 : }
1195 :
1196 0 : if (m->clazz != NULL)
1197 0 : utf_display_printable_ascii_classname(m->clazz->name);
1198 : else
1199 0 : printf("NULL");
1200 0 : printf(".");
1201 0 : utf_display_printable_ascii(m->name);
1202 0 : utf_display_printable_ascii(m->descriptor);
1203 :
1204 0 : method_printflags(m);
1205 : }
1206 : #endif /* !defined(NDEBUG) */
1207 :
1208 :
1209 : /* method_println **************************************************************
1210 :
1211 : Prints a method plus new line to stdout like:
1212 :
1213 : java.lang.Object.<init>()V
1214 :
1215 : *******************************************************************************/
1216 :
1217 : #if !defined(NDEBUG)
1218 0 : void method_println(methodinfo *m)
1219 : {
1220 0 : if (opt_debugcolor) printf("\033[31m"); /* red */
1221 0 : method_print(m);
1222 0 : if (opt_debugcolor) printf("\033[m");
1223 0 : printf("\n");
1224 0 : }
1225 : #endif /* !defined(NDEBUG) */
1226 :
1227 :
1228 : /* method_methodref_print ******************************************************
1229 :
1230 : Prints a method reference to stdout.
1231 :
1232 : *******************************************************************************/
1233 :
1234 : #if !defined(NDEBUG)
1235 0 : void method_methodref_print(constant_FMIref *mr)
1236 : {
1237 0 : if (!mr) {
1238 0 : printf("(constant_FMIref *)NULL");
1239 0 : return;
1240 : }
1241 :
1242 0 : if (mr->is_resolved()) {
1243 0 : printf("<method> ");
1244 0 : method_print(mr->p.method);
1245 : }
1246 : else {
1247 0 : printf("<methodref> ");
1248 0 : utf_display_printable_ascii_classname(mr->p.classref->name);
1249 0 : printf(".");
1250 0 : utf_display_printable_ascii(mr->name);
1251 0 : utf_display_printable_ascii(mr->descriptor);
1252 : }
1253 : }
1254 : #endif /* !defined(NDEBUG) */
1255 :
1256 :
1257 : /* method_methodref_println ****************************************************
1258 :
1259 : Prints a method reference to stdout, followed by a newline.
1260 :
1261 : *******************************************************************************/
1262 :
1263 : #if !defined(NDEBUG)
1264 0 : void method_methodref_println(constant_FMIref *mr)
1265 : {
1266 0 : method_methodref_print(mr);
1267 0 : printf("\n");
1268 0 : }
1269 : #endif /* !defined(NDEBUG) */
1270 :
1271 :
1272 : namespace cacao {
1273 : namespace {
1274 :
1275 0 : inline OStream& method_printflags_OS(OStream &OS, const struct methodinfo &m)
1276 : {
1277 0 : if (m.flags & ACC_PUBLIC) OS << " PUBLIC" ;
1278 0 : if (m.flags & ACC_PRIVATE) OS << " PRIVATE" ;
1279 0 : if (m.flags & ACC_PROTECTED) OS << " PROTECTED" ;
1280 0 : if (m.flags & ACC_STATIC) OS << " STATIC" ;
1281 0 : if (m.flags & ACC_FINAL) OS << " FINAL" ;
1282 0 : if (m.flags & ACC_SYNCHRONIZED) OS << " SYNCHRONIZED" ;
1283 0 : if (m.flags & ACC_VOLATILE) OS << " VOLATILE" ;
1284 0 : if (m.flags & ACC_TRANSIENT) OS << " TRANSIENT" ;
1285 0 : if (m.flags & ACC_NATIVE) OS << " NATIVE" ;
1286 0 : if (m.flags & ACC_INTERFACE) OS << " INTERFACE" ;
1287 0 : if (m.flags & ACC_ABSTRACT) OS << " ABSTRACT" ;
1288 0 : if (m.flags & ACC_METHOD_BUILTIN) OS << " (builtin)" ;
1289 0 : if (m.flags & ACC_METHOD_MONOMORPHIC) OS << " (mono)" ;
1290 0 : if (m.flags & ACC_METHOD_IMPLEMENTED) OS << " (impl)" ;
1291 0 : return OS;
1292 : }
1293 : } // end anonymous namespace
1294 :
1295 0 : OStream& operator<<(OStream &OS, const struct methodinfo &m)
1296 : {
1297 : OS << (Utf8String)m.clazz->name << "."
1298 : << (Utf8String)m.name
1299 0 : << (Utf8String)m.descriptor;
1300 0 : method_printflags_OS(OS,m);
1301 0 : return OS;
1302 : }
1303 :
1304 : } // end namespace cacao
1305 :
1306 : /*
1307 : * These are local overrides for various environment variables in Emacs.
1308 : * Please do not remove this and leave it at the end of the file, where
1309 : * Emacs will automagically detect them.
1310 : * ---------------------------------------------------------------------
1311 : * Local variables:
1312 : * mode: c++
1313 : * indent-tabs-mode: t
1314 : * c-basic-offset: 4
1315 : * tab-width: 4
1316 : * End:
1317 : * vim:noexpandtab:sw=4:ts=4:
1318 : */
|