Line data Source code
1 : /* src/vm/descriptor.cpp - checking and parsing of field / method descriptors
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 : #include "vm/descriptor.hpp"
26 : #include "config.h" // for ENABLE_JIT
27 :
28 : #include <cassert> // for assert
29 : #include <cstdarg> // for va_end, va_list, va_start
30 :
31 : #include "mm/memory.hpp" // for MNEW, MMOVE
32 :
33 : #include "threads/mutex.hpp" // for Mutex
34 :
35 : #include "toolbox/OStream.hpp" // for OStream
36 : #include "toolbox/buffer.hpp" // for Buffer
37 : #include "toolbox/logging.hpp" // for LOG
38 :
39 : #include "vm/exceptions.hpp"
40 : #include "vm/global.hpp" // for Type::TYPE_ADR, etc
41 : #include "vm/options.hpp"
42 : #include "vm/primitive.hpp" // for PrimitiveType, etc
43 : #include "vm/references.hpp" // for constant_classref
44 : #include "vm/types.hpp" // for u4, u1, s4, s2, u2
45 : #include "vm/utf8.hpp" // for Utf8String, operator<<, etc
46 : #include "vm/vm.hpp" // for vm_abort
47 :
48 : #include "vm/jit/abi.hpp" // for md_param_alloc, etc
49 :
50 : struct classinfo;
51 :
52 : using namespace cacao;
53 :
54 : #define DEBUG_NAME "descriptor"
55 :
56 :
57 : /***
58 : *
59 : * Field & method descriptor parsing
60 : *
61 : * See JVM Spec §4.3.2 (Field Descriptors) and §4.3.3 (Method Descriptors)
62 : *
63 : * All methods return true on success and throw an exception on error.
64 : * They also check if the parsed type is valid for its position, for example
65 : * a field type can't be void but a return type can.
66 : *
67 : * Calling a check or parse method consumes the input.
68 : * In the following example the call to parse_field_descriptor() will fail
69 : * because check_field_descriptor() has consumed the whole descriptor.
70 : * @code
71 : * DescriptorParser p(pool, Utf8String::from_utf8("J"));
72 : * if (!p.check_field_descriptor())
73 : * return false;
74 : * if (!p.parse_field_descriptor(&t))
75 : * return false;
76 : * @endcode
77 : */
78 : struct DescriptorParser {
79 : DescriptorParser(DescriptorPool *pool, Utf8String desc);
80 :
81 : /***
82 : * Check if descriptor is valid.
83 : * Any class references in descriptor will be added to pool
84 : */
85 : bool check_field_descriptor();
86 : bool check_param_descriptor(Type &dst);
87 : bool check_return_descriptor();
88 :
89 : /***
90 : * Parse descriptor into typedesc.
91 : * Descriptor must have previously been checked with check_*_descriptor()
92 : * All class references are looked up in pool.
93 : */
94 : bool parse_field_descriptor(typedesc *dst);
95 : bool parse_param_descriptor(typedesc *dst);
96 : bool parse_return_descriptor(typedesc *dst);
97 :
98 : /***
99 : * Start parsing a method descriptors parameter list
100 : */
101 : bool start_param_list();
102 :
103 : /***
104 : * Check if the parameter list we are currently parsing
105 : * has more parameters to parse.
106 : */
107 : bool has_more_params();
108 : private:
109 : enum ParserFlag {
110 : FORBID_VOID_TYPE,
111 : EXPECT_END_OF_INPUT
112 : };
113 :
114 : enum ParseResult {
115 : PARSE_ERROR,
116 : PRIMITIVE_TYPE,
117 : REFERENCE_TYPE
118 : };
119 :
120 :
121 : template<int flags>
122 2112362 : bool check_type(const char *descriptor_type, Type& t);
123 :
124 : template<int flags>
125 2112353 : bool parse_type(const char *descriptor_type, typedesc *t);
126 :
127 : template<int flags>
128 : ParseResult parse_type(Type& t, PrimitiveType& p,
129 : Utf8String& classname, size_t& arraydim);
130 :
131 : bool parse_classname(Utf8String& classname);
132 : bool parse_arraytype(Utf8String& classname, size_t& arraydim);
133 :
134 : bool skip_classname();
135 :
136 : bool read(char&);
137 : void unread();
138 :
139 : bool has_more_input() const;
140 :
141 : /// throws a classformat error and returns false
142 : bool throw_error(const char *reason, ...);
143 :
144 : DescriptorPool *const pool;
145 : const char *descriptor_type; // what kind of descriptor we are currently parsing
146 : const char *pos, *end; // text of descriptor
147 : };
148 :
149 2241356 : inline DescriptorParser::DescriptorParser(DescriptorPool *pool, Utf8String desc)
150 2241356 : : pool(pool), pos(desc.begin()), end(desc.end()) {}
151 :
152 78559 : inline bool DescriptorParser::check_field_descriptor() {
153 : Type dummy;
154 :
155 78559 : return check_type<FORBID_VOID_TYPE | EXPECT_END_OF_INPUT>("field", dummy);
156 : }
157 991681 : inline bool DescriptorParser::check_param_descriptor(Type &dst) {
158 991681 : return check_type<FORBID_VOID_TYPE>("parameter", dst);
159 : }
160 1042122 : inline bool DescriptorParser::check_return_descriptor() {
161 : Type dummy;
162 :
163 1042122 : return check_type<EXPECT_END_OF_INPUT>("return type", dummy);
164 : }
165 :
166 78557 : inline bool DescriptorParser::parse_field_descriptor(typedesc *dst) {
167 78557 : return parse_type<FORBID_VOID_TYPE | EXPECT_END_OF_INPUT>("field", dst);
168 : }
169 991678 : inline bool DescriptorParser::parse_param_descriptor(typedesc *dst) {
170 991678 : return parse_type<FORBID_VOID_TYPE>("parameter", dst);
171 : }
172 1042118 : inline bool DescriptorParser::parse_return_descriptor(typedesc *dst) {
173 1042118 : return parse_type<EXPECT_END_OF_INPUT>("return type", dst);
174 : }
175 :
176 2084240 : inline bool DescriptorParser::start_param_list() {
177 2084240 : descriptor_type = "method";
178 :
179 2084240 : char c = 0;
180 :
181 2084240 : if (!read(c))
182 0 : return false;
183 :
184 2084240 : if (c != '(')
185 0 : return throw_error("Method descriptor does not start with '('");
186 :
187 2084240 : return true;
188 : }
189 :
190 4067599 : inline bool DescriptorParser::has_more_params() {
191 4067599 : if (!has_more_input())
192 0 : return false;
193 4067599 : if (*pos == ')') {
194 2084240 : pos++;
195 2084240 : return false;
196 : }
197 :
198 1983359 : return true;
199 : }
200 :
201 6308955 : inline bool DescriptorParser::has_more_input() const {
202 6308955 : return pos != end;
203 : }
204 :
205 : template<int flags>
206 : inline bool DescriptorParser::check_type(const char *descriptor_type, Type& dst) {
207 2112362 : this->descriptor_type = descriptor_type;
208 :
209 : Type type;
210 : PrimitiveType primtype;
211 2112362 : Utf8String classname;
212 2112362 : size_t arraydim = 0;
213 :
214 2112362 : switch (parse_type<flags>(type, primtype, classname, arraydim)) {
215 : case PARSE_ERROR:
216 0 : return false;
217 : case PRIMITIVE_TYPE:
218 1049986 : dst = type;
219 1049986 : return true;
220 : case REFERENCE_TYPE:
221 : // descriptor is array or class type
222 1062376 : dst = type;
223 1062376 : return pool->add_class(classname);
224 : default:
225 0 : assert(false);
226 : return false;
227 : }
228 : }
229 :
230 : template<int flags>
231 : inline bool DescriptorParser::parse_type(const char *descriptor_type, typedesc *dst) {
232 2112353 : this->descriptor_type = descriptor_type;
233 :
234 2112353 : Type type = TYPE_INT;
235 2112353 : PrimitiveType primtype = PRIMITIVETYPE_INT;
236 2112353 : Utf8String classname;
237 2112353 : size_t arraydim = 0;
238 :
239 2112353 : switch (parse_type<flags>(type, primtype, classname, arraydim)) {
240 : case PARSE_ERROR:
241 0 : return false;
242 : case PRIMITIVE_TYPE:
243 1049982 : dst->classref = NULL;
244 1049982 : dst->type = type;
245 1049982 : dst->primitivetype = primtype;
246 1049982 : dst->arraydim = 0;
247 1049982 : return true;
248 : case REFERENCE_TYPE:
249 1062371 : dst->classref = pool->lookup_classref(classname);
250 1062371 : dst->type = TYPE_ADR;
251 1062371 : dst->primitivetype = (PrimitiveType) TYPE_ADR;
252 1062371 : dst->arraydim = arraydim;
253 1062371 : return true;
254 : default:
255 0 : assert(false);
256 : return false;
257 : }
258 : }
259 :
260 : template<int flags>
261 4224715 : inline DescriptorParser::ParseResult DescriptorParser::parse_type(Type& t,
262 : PrimitiveType& p,
263 : Utf8String& classname,
264 : size_t& arraydim) {
265 : ParseResult result;
266 4224715 : char c = 0;
267 :
268 4224715 : if (!read(c))
269 0 : return PARSE_ERROR;
270 :
271 4224715 : switch (c) {
272 : case 'B':
273 18514 : t = TYPE_INT;
274 18514 : p = PRIMITIVETYPE_BYTE;
275 18514 : result = PRIMITIVE_TYPE;
276 18514 : break;
277 : case 'C':
278 73496 : t = TYPE_INT;
279 73496 : p = PRIMITIVETYPE_CHAR;
280 73496 : result = PRIMITIVE_TYPE;
281 73496 : break;
282 : case 'D':
283 64678 : t = TYPE_DBL;
284 64678 : p = PRIMITIVETYPE_DOUBLE;
285 64678 : result = PRIMITIVE_TYPE;
286 64678 : break;
287 : case 'F':
288 42170 : t = TYPE_FLT;
289 42170 : p = PRIMITIVETYPE_FLOAT;
290 42170 : result = PRIMITIVE_TYPE;
291 42170 : break;
292 : case 'I':
293 766696 : t = TYPE_INT;
294 766696 : p = PRIMITIVETYPE_INT;
295 766696 : result = PRIMITIVE_TYPE;
296 766696 : break;
297 : case 'J':
298 117336 : t = TYPE_LNG;
299 117336 : p = PRIMITIVETYPE_LONG;
300 117336 : result = PRIMITIVE_TYPE;
301 117336 : break;
302 : case 'S':
303 16120 : t = TYPE_INT;
304 16120 : p = PRIMITIVETYPE_SHORT;
305 16120 : result = PRIMITIVE_TYPE;
306 16120 : break;
307 : case 'Z':
308 321158 : t = TYPE_INT;
309 321158 : p = PRIMITIVETYPE_BOOLEAN;
310 321158 : result = PRIMITIVE_TYPE;
311 321158 : break;
312 : case 'V':
313 : if (flags & FORBID_VOID_TYPE) {
314 : throw_error("Type void is illegal");
315 : return PARSE_ERROR;
316 : }
317 :
318 679800 : t = TYPE_VOID;
319 679800 : p = PRIMITIVETYPE_VOID;
320 679800 : result = PRIMITIVE_TYPE;
321 679800 : break;
322 :
323 : case 'L': // object (L<classname>;)
324 1883365 : if (!parse_classname(classname))
325 0 : return PARSE_ERROR;
326 :
327 1883365 : t = TYPE_ADR;
328 1883365 : arraydim = 0;
329 1883365 : result = REFERENCE_TYPE;
330 1883365 : break;
331 : case '[': // array type
332 241382 : unread(); // parse_arraytype counts the '['
333 :
334 241382 : if (!parse_arraytype(classname, arraydim))
335 0 : return PARSE_ERROR;
336 :
337 241382 : t = TYPE_ADR;
338 241382 : result = REFERENCE_TYPE;
339 241382 : break;
340 : default:
341 0 : throw_error("Illegal character '%c'", c);
342 0 : return PARSE_ERROR;
343 : }
344 :
345 2241356 : if ((flags & EXPECT_END_OF_INPUT) && has_more_input()) {
346 0 : throw_error("Unexpected characters at end of descriptor");
347 0 : return PARSE_ERROR;
348 : }
349 :
350 4224715 : return result;
351 : }
352 :
353 1883365 : inline bool DescriptorParser::parse_classname(Utf8String& classname) {
354 : // find end of classname
355 :
356 1883365 : const char *mark = pos;
357 :
358 1883365 : if (!skip_classname())
359 0 : return false;
360 :
361 : // utf8 string from classname
362 :
363 1883365 : Utf8String str = Utf8String::from_utf8(mark, pos - mark - 1);
364 :
365 1883365 : if (str == NULL)
366 0 : return throw_error("Class name is not valid UTF-8");
367 :
368 : // done
369 :
370 1883365 : classname = str;
371 1883365 : return true;
372 : }
373 :
374 241382 : inline bool DescriptorParser::parse_arraytype(Utf8String& classname, size_t& arraydim) {
375 241382 : size_t array_dimension = 0;
376 :
377 241382 : const char *mark = pos;
378 :
379 241382 : char c = 0;
380 :
381 : // skip leading '['
382 :
383 246300 : while (true) {
384 487682 : if (!read(c))
385 0 : return false;
386 487682 : if (c != '[')
387 : break;
388 :
389 246300 : array_dimension++;
390 : }
391 :
392 241382 : if (array_dimension > 255)
393 0 : return throw_error("Too large array dimension: %lu", array_dimension);
394 :
395 : // check if element type is valid
396 :
397 241382 : switch (c) {
398 : case 'B': // primitive type
399 : case 'C':
400 : case 'D':
401 : case 'F':
402 : case 'I':
403 : case 'J':
404 : case 'S':
405 : case 'Z':
406 97300 : break;
407 :
408 : case 'L': // object (L<classname>;)
409 144082 : if(!skip_classname())
410 0 : return false;
411 :
412 144082 : break;
413 :
414 : default:
415 0 : return throw_error("Illegal type of array element '%c'", c);
416 : }
417 :
418 241382 : classname = Utf8String::from_utf8(mark, pos - mark);
419 :
420 241382 : if (classname == NULL)
421 0 : return throw_error("Name is not valid utf8: '%s'", mark);
422 :
423 241382 : arraydim = array_dimension;
424 :
425 241382 : return true;
426 : }
427 :
428 40016889 : inline bool DescriptorParser::skip_classname() {
429 : // classname is delimited by 'L' and ';'
430 : // but at this point the 'L' was already consumed
431 :
432 37989442 : while (true) {
433 40016889 : char c = 0;
434 :
435 40016889 : if (!read(c))
436 0 : return false;
437 40016889 : if (c == ';')
438 2027447 : return true;
439 : }
440 : }
441 :
442 46813526 : inline bool DescriptorParser::read(char& c) {
443 46813526 : if (pos == end)
444 0 : return throw_error("Truncated descriptor");
445 :
446 46813526 : c = *pos++;
447 46813526 : return true;
448 : }
449 :
450 241382 : inline void DescriptorParser::unread() {
451 241382 : pos--;
452 241382 : }
453 :
454 0 : inline bool DescriptorParser::throw_error(const char *reason, ...) {
455 0 : assert(descriptor_type);
456 :
457 0 : Buffer<> buf;
458 : va_list ap;
459 :
460 0 : va_start(ap, reason);
461 0 : buf.write("Invalid ").write(descriptor_type).write(" descriptor: ").writevf(reason, ap);
462 0 : va_end(ap);
463 :
464 0 : exceptions_throw_classformaterror(pool->get_referer(), buf.utf8_str());
465 0 : return false;
466 : }
467 :
468 : //******************************************************************************
469 : // Descriptor pool
470 : //******************************************************************************
471 :
472 : // initial number of entries for the classrefhash of a descriptor pool
473 : #define CLASSREFHASH_INIT_SIZE 256
474 :
475 : // initial number of entries for the fieldrefhash of a descriptor pool
476 : #define FIELDREFHASH_INIT_SIZE 256
477 :
478 :
479 35953 : DescriptorPool::DescriptorPool(classinfo *referer) : classrefhash(CLASSREFHASH_INIT_SIZE),
480 : fieldrefhash(FIELDREFHASH_INIT_SIZE),
481 : referer(referer),
482 : fieldcount(0),
483 : methodcount(0),
484 : paramcount(0),
485 : descriptorsize(0),
486 : classrefs(NULL),
487 : mutex(new Mutex()),
488 : descriptors(NULL),
489 35953 : descriptors_next(NULL) {}
490 :
491 : /***
492 : * Allocate an object from the descriptor pools private block of memory.
493 : * This function performs no checks, you can only allocate objects you have
494 : * previously added via add_field or add_method.
495 : */
496 : template<typename T>
497 3041703 : T *DescriptorPool::allocate(size_t size) {
498 3041703 : T *t = (T*) descriptors_next;
499 :
500 3041703 : descriptors_next += size;
501 :
502 3041703 : return t;
503 : }
504 :
505 :
506 : /***
507 : * Add the given class reference to the pool
508 : *
509 : * @return false iff an exception was thrown.
510 : */
511 1400320 : bool DescriptorPool::add_class(Utf8String name) {
512 : LOG("DescriptorPool::add_class(" << name << ")");
513 :
514 1400320 : assert(name);
515 :
516 : /* find a place in the hashtable */
517 :
518 1400320 : ClassrefHash::EntryRef ref = classrefhash.find(name);
519 :
520 1400320 : if (ref)
521 979647 : return true; // classname was already present
522 :
523 : /* check if the name is a valid classname */
524 :
525 420673 : if (!name.is_valid_name()) {
526 0 : exceptions_throw_classformaterror(referer, "Invalid class name");
527 0 : return false; /* exception */
528 : }
529 :
530 : /* XXX check maximum array dimension */
531 :
532 420673 : classrefhash.insert(ref, name, classrefhash.size());
533 420673 : return true;
534 : }
535 :
536 :
537 : /***
538 : * Check the given descriptor and add it to the pool
539 : *
540 : * @param desc the field descriptor to add.
541 : * @return false iff an exception has been thrown
542 : */
543 214307 : bool DescriptorPool::add_field(Utf8String desc) {
544 : LOG("DescriptorPool::add_field(" << ((void*) this) << ", " << desc << ")\n");
545 :
546 : // check if field descriptor was already in table
547 :
548 214307 : FieldrefHash::EntryRef ref = fieldrefhash.find(desc);
549 :
550 214307 : if (ref)
551 135748 : return true;
552 :
553 : // check the descriptor
554 :
555 78559 : DescriptorParser parser(this, desc);
556 :
557 78559 : if (!parser.check_field_descriptor())
558 0 : return false;
559 :
560 : // add the descriptor to the pool
561 :
562 78559 : fieldrefhash.insert(ref, desc, (typedesc*) NULL);
563 :
564 : // done
565 :
566 78559 : fieldcount++;
567 78559 : return true;
568 : }
569 :
570 : /***
571 : * Check the given descriptor and add it to the pool
572 : *
573 : * @param desc the method descriptor to add.
574 : * @return false iff an exception has been thrown
575 : */
576 1042122 : ssize_t DescriptorPool::add_method(Utf8String desc) {
577 : LOG("DescriptorPool::add_method(" << ((void*) this) << ", " << desc << ")\n");
578 :
579 1042122 : assert(desc);
580 :
581 : // check the descriptor
582 :
583 1042122 : DescriptorParser parser(this, desc);
584 :
585 1042122 : size_t argcount = 0;
586 :
587 : // check parameters
588 :
589 1042122 : if (!parser.start_param_list())
590 0 : return -1;
591 :
592 3075925 : while (parser.has_more_params()) {
593 : // We cannot count the `this' argument here because
594 : // we don't know if the method is static.
595 :
596 991681 : paramcount++;
597 :
598 : Type type;
599 :
600 991681 : if (!parser.check_param_descriptor(type))
601 0 : return -1;
602 :
603 991681 : argcount += IS_2_WORD_TYPE(type) ? 2 : 1;
604 : }
605 :
606 1042122 : if (argcount > 255) {
607 0 : exceptions_throw_classformaterror(referer, "Too many arguments in signature");
608 0 : return -1;
609 : }
610 :
611 : // check return type
612 :
613 1042122 : if (!parser.check_return_descriptor())
614 0 : return -1;
615 :
616 : // done
617 :
618 1042122 : methodcount++;
619 1042122 : return argcount;
620 : }
621 :
622 :
623 : /***
624 : * Create a table containing all the classrefs which were added to the pool
625 : *
626 : * @param[out] count if count is non-NULL, this is set to the number
627 : * of classrefs in the table
628 : * @return a pointer to the constant_classref table
629 : */
630 35953 : constant_classref *DescriptorPool::create_classrefs(s4 *count)
631 : {
632 : size_t nclasses;
633 :
634 35953 : nclasses = classrefhash.size();
635 35953 : classrefs = MNEW(constant_classref,nclasses);
636 :
637 : // fill the constant_classref structs
638 :
639 456626 : for (ClassrefHash::Iterator it = classrefhash.begin(), end = classrefhash.end(); it != end; ++it) {
640 420673 : new (classrefs + it->value()) constant_classref(referer, it->key());
641 : }
642 :
643 35953 : if (count)
644 35790 : *count = nclasses;
645 :
646 35953 : return classrefs;
647 : }
648 :
649 :
650 : /***
651 : * Return the constant_classref for the given class name
652 : *
653 : * @param classname name of the class to look up
654 : * @return a pointer to the constant_classref, or
655 : * NULL if an exception has been thrown
656 : */
657 1541093 : constant_classref *DescriptorPool::lookup_classref(Utf8String classname)
658 : {
659 1541093 : assert(classrefs);
660 1541093 : assert(classname);
661 :
662 1541093 : if (ClassrefHash::EntryRef ref = classrefhash.find(classname)) {
663 1541093 : return classrefs + ref->value();
664 : } else {
665 0 : exceptions_throw_internalerror("Class reference not found in descriptor pool");
666 0 : return NULL;
667 : }
668 : }
669 :
670 :
671 : /***
672 : * Allocate space for the parsed descriptors
673 : *
674 : * @note
675 : * This function must be called after all descriptors have been added
676 : * with DescriptorPool::add.
677 : */
678 35953 : void DescriptorPool::alloc_parsed_descriptors() {
679 : /* TWISTI: paramcount + 1: we don't know if the method is static or */
680 : /* not, i have no better solution yet. */
681 :
682 : size_t size = fieldcount * sizeof(typedesc)
683 : + methodcount * (sizeof(methoddesc) - sizeof(typedesc))
684 : + paramcount * sizeof(typedesc)
685 35953 : + methodcount * sizeof(typedesc); // possible `this' pointer
686 :
687 35953 : descriptorsize = size;
688 :
689 35953 : if (size) {
690 35141 : descriptors = MNEW(u1, size);
691 35141 : descriptors_next = descriptors;
692 : }
693 35953 : }
694 :
695 :
696 : /***
697 : * Parse the given field descriptor
698 : *
699 : * @param pool the descriptor_pool
700 : * @param desc the field descriptor
701 : * @return a pointer to the parsed field descriptor, or
702 : * NULL if an exception has been thrown
703 : *
704 : * @note
705 : * DescriptorPool::alloc_parsed_descriptors must be called (once)
706 : * before this function is used.
707 : */
708 214303 : typedesc *DescriptorPool::parse_field_descriptor(Utf8String desc) {
709 214303 : assert(descriptors);
710 214303 : assert(descriptors_next);
711 :
712 : // lookup the descriptor in the hashtable
713 :
714 214303 : FieldrefHash::EntryRef ref = fieldrefhash.find(desc);
715 :
716 214303 : assert(ref);
717 :
718 214303 : typedesc *td = ref->value();
719 :
720 214303 : if (!td) {
721 : // field has been parsed yet.
722 78557 : td = allocate<typedesc>();
723 :
724 78557 : DescriptorParser parser(this, desc);
725 :
726 78557 : if (!parser.parse_field_descriptor(td))
727 0 : return NULL;
728 :
729 78557 : ref->value() = td;
730 : }
731 :
732 214303 : return td;
733 : }
734 :
735 :
736 : /***
737 : * Parse the given method descriptor
738 : *
739 : * @param desc the method descriptor
740 : * @param mflags the method flags
741 : * @param thisclass classref to the class containing the method.
742 : * This is ignored if mflags contains ACC_STATIC.
743 : * The classref is stored for inserting the 'this' argument.
744 : * @return a pointer to the parsed method descriptor,
745 : * or NULL if an exception has been thrown
746 : *
747 : * @note
748 : * descriptor_pool::alloc_parsed_descriptors must be called
749 : * (once) before this function is used.
750 : */
751 1042118 : methoddesc *DescriptorPool::parse_method_descriptor(Utf8String desc,
752 : s4 mflags,
753 : constant_classref *thisclass) {
754 : LOG("DescriptorPool::parse_method_descriptor(" << ((void*) this) << ", " << mflags << ", " << thisclass << ")\n");
755 :
756 1042118 : assert(descriptors);
757 1042118 : assert(descriptors_next);
758 :
759 : // check that it is a method descriptor
760 :
761 1042118 : if (desc[0] != '(') {
762 : exceptions_throw_classformaterror(referer,
763 0 : "Field descriptor used in method reference");
764 0 : return NULL;
765 : }
766 :
767 1042118 : methoddesc *md = allocate<methoddesc>(offsetof(methoddesc, paramtypes));
768 1042118 : md->pool_lock = mutex;
769 :
770 1042118 : s2 paramcount = 0;
771 1042118 : s2 paramslots = 0;
772 :
773 : // count the `this' pointer
774 :
775 1042118 : if ((mflags != ACC_UNDEF) && !(mflags & ACC_STATIC)) {
776 361559 : typedesc *td = allocate<typedesc>();
777 :
778 361559 : td->type = TYPE_ADR;
779 361559 : td->arraydim = 0;
780 361559 : td->classref = thisclass;
781 :
782 361559 : paramcount++;
783 361559 : paramslots++;
784 : }
785 :
786 : // parse parameters
787 :
788 1042118 : DescriptorParser parser(this, desc);
789 :
790 1042118 : if (!parser.start_param_list())
791 0 : return NULL;
792 :
793 3075914 : while (parser.has_more_params()) {
794 : // parse a parameter type
795 :
796 991678 : typedesc *td = allocate<typedesc>();
797 :
798 991678 : if (!parser.parse_param_descriptor(td))
799 0 : return NULL;
800 :
801 991678 : if (IS_2_WORD_TYPE(td->type))
802 49786 : paramslots++;
803 :
804 991678 : paramcount++;
805 991678 : paramslots++;
806 : }
807 :
808 1042118 : md->paramcount = paramcount;
809 1042118 : md->paramslots = paramslots;
810 :
811 : // Skip possible `this' pointer in paramtypes array to allow a possible
812 : // memory move later in parse.
813 : // We store the thisclass reference, so we can later correctly fill in
814 : // the parameter slot of the 'this' argument.
815 :
816 1042118 : if (mflags == ACC_UNDEF) {
817 567791 : typedesc *td = allocate<typedesc>();
818 :
819 567791 : td->classref = thisclass;
820 : }
821 :
822 : // parse return type
823 :
824 1042118 : if (!parser.parse_return_descriptor(&md->returntype))
825 0 : return NULL;
826 :
827 : // If mflags != ACC_UNDEF we parse a real loaded method, so do
828 : // param prealloc. Otherwise we do this in stack analysis.
829 :
830 1042118 : if (mflags != ACC_UNDEF) {
831 474327 : if (md->paramcount > 0) {
832 : // allocate memory for params
833 :
834 451575 : md->params = MNEW(paramdesc, md->paramcount);
835 : } else {
836 22752 : md->params = METHODDESC_NOPARAMS;
837 : }
838 :
839 : // fill the paramdesc
840 : // md_param_alloc has to be called if md->paramcount == 0,
841 : // too, so it can make the reservation for the Linkage Area,
842 : // Return Register...
843 :
844 : #if defined(ENABLE_JIT)
845 : // As builtin-functions are native functions, we have
846 : // to pre-allocate for the native ABI.
847 :
848 474327 : if (mflags & ACC_METHOD_BUILTIN)
849 4401 : md_param_alloc_native(md);
850 : else
851 469926 : md_param_alloc(md);
852 : #endif
853 :
854 : // params already initialized; no need to lock
855 474327 : md->pool_lock = NULL;
856 : } else {
857 : // params will be allocated later by
858 : // methoddesc::params_from_paramtypes if necessary
859 :
860 567791 : md->params = NULL;
861 : }
862 :
863 1042118 : return md;
864 : }
865 :
866 : /***
867 : * Create the paramdescs for a method descriptor. This function is
868 : * called when we know whether the method is static or not. This
869 : * function does nothing if md->params != NULL (checked atomically).
870 : *
871 : * @param mflags the ACC_* access flags of the method. Only the
872 : * ACC_STATIC bit is checked.
873 : * The value ACC_UNDEF is NOT allowed.
874 : *
875 : * @post parms != NULL
876 : */
877 880472 : void methoddesc::params_from_paramtypes(s4 mflags) {
878 880472 : bool has_lock = pool_lock != NULL;
879 :
880 880472 : if (pool_lock)
881 637446 : pool_lock->lock();
882 880473 : if (params) {
883 706858 : if (has_lock)
884 468775 : pool_lock->unlock();
885 706858 : return;
886 : }
887 :
888 173615 : assert(params == NULL);
889 173615 : assert(mflags != ACC_UNDEF);
890 :
891 173615 : typedesc *td = paramtypes;
892 :
893 : /* check for `this' pointer */
894 :
895 173615 : if (!(mflags & ACC_STATIC)) {
896 : constant_classref *thisclass;
897 :
898 : /* fetch class reference from reserved param slot */
899 145688 : thisclass = td[paramcount].classref;
900 145688 : assert(thisclass);
901 :
902 145688 : if (paramcount > 0) {
903 : /* shift param types by 1 argument */
904 73803 : MMOVE(td + 1, td, typedesc, paramcount);
905 : }
906 :
907 : /* fill in first argument `this' */
908 :
909 145688 : td->type = TYPE_ADR;
910 145688 : td->primitivetype = (PrimitiveType) TYPE_ADR;
911 145688 : td->arraydim = 0;
912 145688 : td->classref = thisclass;
913 :
914 145688 : paramcount++;
915 145688 : paramslots++;
916 : }
917 :
918 : // if the method has params, process them
919 :
920 173615 : if (paramcount > 0) {
921 : // allocate memory for params
922 166552 : params = MNEW(paramdesc, paramcount);
923 : } else {
924 7063 : params = METHODDESC_NOPARAMS;
925 : }
926 :
927 : // fill the paramdesc
928 : // md_param_alloc has to be called if md->paramcount == 0, too, so
929 : // it can make the reservation for the Linkage Area, Return Register, ...
930 :
931 : #if defined(ENABLE_JIT)
932 : // As builtin-functions are native functions, we have to
933 : // pre-allocate for the native ABI.
934 :
935 173615 : if (mflags & ACC_METHOD_BUILTIN)
936 0 : md_param_alloc_native(this);
937 : else
938 173615 : md_param_alloc(this);
939 : #endif
940 :
941 173615 : if (has_lock)
942 168671 : pool_lock->unlock();
943 : }
944 :
945 0 : classinfo *DescriptorPool::get_referer() {
946 0 : return referer;
947 : }
948 :
949 : /***
950 : * Get the sizes of the class reference table and the parsed descriptors
951 : *
952 : * @param[out] classrefsize set to size of the class reference table
953 : * @param[out] descsize set to size of the parsed descriptors
954 : *
955 : * @note
956 : * This function may only be called after both
957 : * descriptor_pool::create_classrefs, and
958 : * descriptor_pool::alloc_parsed_descriptors
959 : * have been called.
960 : */
961 0 : void DescriptorPool::get_sizes(size_t *classrefsize, size_t *descsize) {
962 0 : assert((!fieldcount && !methodcount) || descriptors);
963 0 : assert(classrefs);
964 0 : assert(classrefsize);
965 0 : assert(descsize);
966 :
967 0 : *classrefsize = classrefhash.size() * sizeof(constant_classref);
968 0 : *descsize = descriptorsize;
969 0 : }
970 :
971 :
972 : /***
973 : * Return the basic type to use for a value with this descriptor.
974 : *
975 : * @pre This function assumes that the descriptor has passed
976 : * DescriptorPool::add_field checks and that it does not start with '('.
977 : */
978 113368 : Type descriptor_to_basic_type(Utf8String descriptor) {
979 113368 : assert(descriptor.size() >= 1);
980 :
981 113368 : switch (descriptor[0]) {
982 : case 'Z':
983 : case 'B':
984 : case 'C':
985 : case 'S':
986 : case 'I':
987 39898 : return TYPE_INT;
988 :
989 : case 'J':
990 13977 : return TYPE_LNG;
991 :
992 : case 'F':
993 2229 : return TYPE_FLT;
994 :
995 : case 'D':
996 1289 : return TYPE_DBL;
997 :
998 : case 'L':
999 : case '[':
1000 55975 : return TYPE_ADR;
1001 :
1002 : default:
1003 0 : vm_abort("descriptor_to_basic_type: invalid type %c", descriptor[0]);
1004 0 : return TYPE_VOID;
1005 : }
1006 : }
1007 :
1008 :
1009 : /****************************************************************************/
1010 : /* DEBUG HELPERS */
1011 : /****************************************************************************/
1012 :
1013 : /***
1014 : * Print the given typedesc to the given stream
1015 : */
1016 0 : void descriptor_debug_print_typedesc(FILE *file,typedesc *d) {
1017 : int ch;
1018 :
1019 0 : if (!d) {
1020 0 : fprintf(file,"(typedesc *)NULL");
1021 0 : return;
1022 : }
1023 :
1024 0 : if (d->type == TYPE_ADR) {
1025 0 : if (d->classref)
1026 0 : utf_fprint_printable_ascii(file,d->classref->name);
1027 : else
1028 0 : fprintf(file,"<class=NULL>");
1029 : }
1030 : else {
1031 0 : switch (d->primitivetype) {
1032 0 : case PRIMITIVETYPE_INT : ch='I'; break;
1033 0 : case PRIMITIVETYPE_CHAR : ch='C'; break;
1034 0 : case PRIMITIVETYPE_BYTE : ch='B'; break;
1035 0 : case PRIMITIVETYPE_SHORT : ch='S'; break;
1036 0 : case PRIMITIVETYPE_BOOLEAN: ch='Z'; break;
1037 0 : case PRIMITIVETYPE_LONG : ch='J'; break;
1038 0 : case PRIMITIVETYPE_FLOAT : ch='F'; break;
1039 0 : case PRIMITIVETYPE_DOUBLE : ch='D'; break;
1040 0 : case PRIMITIVETYPE_VOID : ch='V'; break;
1041 0 : default : ch='!';
1042 : }
1043 0 : fputc(ch,file);
1044 : }
1045 0 : if (d->arraydim)
1046 0 : fprintf(file,"[%d]",d->arraydim);
1047 : }
1048 :
1049 : /***
1050 : * Print the given paramdesc to the given stream
1051 : */
1052 0 : void descriptor_debug_print_paramdesc(FILE *file,paramdesc *d) {
1053 0 : if (!d) {
1054 0 : fprintf(file,"(paramdesc *)NULL");
1055 0 : return;
1056 : }
1057 :
1058 0 : if (d->inmemory) {
1059 0 : fprintf(file,"<m%d>",d->regoff);
1060 : }
1061 : else {
1062 0 : fprintf(file,"<r%d>",d->regoff);
1063 : }
1064 : }
1065 :
1066 : /***
1067 : * Print the given methoddesc to the given stream
1068 : */
1069 0 : void descriptor_debug_print_methoddesc(FILE *file,methoddesc *d) {
1070 : int i;
1071 :
1072 0 : if (!d) {
1073 0 : fprintf(file,"(methoddesc *)NULL");
1074 0 : return;
1075 : }
1076 :
1077 0 : fputc('(',file);
1078 0 : for (i=0; i<d->paramcount; ++i) {
1079 0 : if (i)
1080 0 : fputc(',',file);
1081 0 : descriptor_debug_print_typedesc(file,d->paramtypes + i);
1082 0 : if (d->params) {
1083 0 : descriptor_debug_print_paramdesc(file,d->params + i);
1084 : }
1085 : }
1086 0 : if (d->params == METHODDESC_NOPARAMS)
1087 0 : fputs("<NOPARAMS>",file);
1088 0 : fputc(')',file);
1089 0 : descriptor_debug_print_typedesc(file,&(d->returntype));
1090 : }
1091 :
1092 :
1093 : /*
1094 : * These are local overrides for various environment variables in Emacs.
1095 : * Please do not remove this and leave it at the end of the file, where
1096 : * Emacs will automagically detect them.
1097 : * ---------------------------------------------------------------------
1098 : * Local variables:
1099 : * mode: c++
1100 : * indent-tabs-mode: t
1101 : * c-basic-offset: 4
1102 : * tab-width: 4
1103 : * End:
1104 : * vim:noexpandtab:sw=4:ts=4:
1105 : */
|