]> gcc.gnu.org Git - gcc.git/blob - libjava/defineclass.cc
49774839abff33106d76d58b3baf129718bcdfaa
[gcc.git] / libjava / defineclass.cc
1 // defineclass.cc - defining a class from .class format.
2
3 /* Copyright (C) 1999, 2000 Free Software Foundation
4
5 This file is part of libgcj.
6
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9 details. */
10
11 /*
12 Author: Kresten Krab Thorup <krab@gnu.org>
13
14 Written using the online versions of Java Language Specification (1st
15 ed.) and The Java Virtual Machine Specification (2nd ed.).
16
17 Future work may include reading (and handling) attributes which are
18 currently being ignored ("InnerClasses", "LineNumber", etc...).
19 */
20
21 #include <config.h>
22
23 #include <java-interp.h>
24
25 #ifdef INTERPRETER
26
27 #include <stdlib.h>
28 #if HAVE_ALLOCA_H
29 #include <alloca.h>
30 #endif
31 #include <java-cpool.h>
32 #include <gcj/cni.h>
33
34 #include <java/lang/Class.h>
35 #include <java/lang/Float.h>
36 #include <java/lang/Double.h>
37 #include <java/lang/Character.h>
38 #include <java/lang/LinkageError.h>
39 #include <java/lang/InternalError.h>
40 #include <java/lang/ClassFormatError.h>
41 #include <java/lang/NoClassDefFoundError.h>
42 #include <java/lang/ClassCircularityError.h>
43 #include <java/lang/ClassNotFoundException.h>
44 #include <java/lang/IncompatibleClassChangeError.h>
45 #include <java/lang/reflect/Modifier.h>
46
47 // we don't verify method names that match these.
48 static _Jv_Utf8Const *clinit_name = _Jv_makeUtf8Const ("<clinit>", 8);
49 static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
50
51
52 // these go in some seperate functions, to avoid having _Jv_InitClass
53 // inserted all over the place.
54 static void throw_internal_error (char *msg)
55 __attribute__ ((__noreturn__));
56 static void throw_no_class_def_found_error (jstring msg)
57 __attribute__ ((__noreturn__));
58 static void throw_no_class_def_found_error (char *msg)
59 __attribute__ ((__noreturn__));
60 static void throw_class_format_error (jstring msg)
61 __attribute__ ((__noreturn__));
62 static void throw_class_format_error (char *msg)
63 __attribute__ ((__noreturn__));
64 static void throw_incompatible_class_change_error (jstring msg)
65 __attribute__ ((__noreturn__));
66 static void throw_class_circularity_error (jstring msg)
67 __attribute__ ((__noreturn__));
68
69 static jdouble long_bits_to_double (jlong);
70 static jfloat int_bits_to_float (jint);
71
72 /**
73 * We define class reading using a class. It is practical, since then
74 * the entire class-reader can be a friend of class Class (it needs to
75 * write all it's different structures); but also because this makes it
76 * easy to make class definition reentrant, and thus two threads can be
77 * defining classes at the same time. This class (_Jv_ClassReader) is
78 * never exposed outside this file, so we don't have to worry about
79 * public or private members here.
80 */
81
82 struct _Jv_ClassReader {
83
84 // do verification? Currently, there is no option to disable this.
85 // This flag just controls the verificaiton done by the class loader;
86 // i.e., checking the integrity of the constant pool; and it is
87 // allways on. You always want this as far as I can see, but it also
88 // controls weither identifiers and type descriptors/signatures are
89 // verified as legal. This could be somewhat more expensive since it
90 // will call Characher.isJavaIdentifier{Start,Part} for each character
91 // in any identifier (field name or method name) it comes by. Thus,
92 // it might be useful to turn off this verification for classes that
93 // come from a trusted source. However, for GCJ, trusted classes are
94 // most likely to be linked in.
95
96 bool verify;
97
98 // input data.
99 unsigned char *bytes;
100 int len;
101
102 // current input position
103 int pos;
104
105 // the constant pool data
106 int pool_count;
107 unsigned char *tags;
108 unsigned int *offsets;
109
110 // the class to define (see java-interp.h)
111 _Jv_InterpClass *def;
112
113 /* check that the given number of input bytes are available */
114 inline void check (int num)
115 {
116 if (pos + num > len)
117 throw_class_format_error ("Premature end of data");
118 }
119
120 /* skip a given number of bytes in input */
121 inline void skip (int num)
122 {
123 check (num);
124 pos += num;
125 }
126
127 /* read an unsignend 1-byte unit */
128 inline static jint get1u (unsigned char* bytes)
129 {
130 return bytes[0];
131 }
132
133 /* read an unsigned 1-byte unit */
134 inline jint read1u ()
135 {
136 skip (1);
137 return get1u (bytes+pos-1);
138 }
139
140 /* read an unsigned 2-byte unit */
141 inline static jint get2u (unsigned char *bytes)
142 {
143 return (((jint)bytes[0]) << 8) | ((jint)bytes[1]);
144 }
145
146 /* read an unsigned 2-byte unit */
147 inline jint read2u ()
148 {
149 skip (2);
150 return get2u (bytes+pos-2);
151 }
152
153 /* read a 4-byte unit */
154 static jint get4 (unsigned char *bytes)
155 {
156 return (((jint)bytes[0]) << 24)
157 | (((jint)bytes[1]) << 16)
158 | (((jint)bytes[2]) << 8)
159 | (((jint)bytes[3]) << 0);
160 }
161
162 /* read a 4-byte unit, (we don't do that quite so often) */
163 inline jint read4 ()
164 {
165 skip (4);
166 return get4 (bytes+pos-4);
167 }
168
169 /* read a 8-byte unit */
170 static jlong get8 (unsigned char* bytes)
171 {
172 return (((jlong)bytes[0]) << 56)
173 | (((jlong)bytes[1]) << 48)
174 | (((jlong)bytes[2]) << 40)
175 | (((jlong)bytes[3]) << 32)
176 | (((jlong)bytes[4]) << 24)
177 | (((jlong)bytes[5]) << 16)
178 | (((jlong)bytes[6]) << 8)
179 | (((jlong)bytes[7]) << 0);
180 }
181
182 /* read a 8-byte unit */
183 inline jlong read8 ()
184 {
185 skip (8);
186 return get8 (bytes+pos-8);
187 }
188
189 inline void check_tag (int index, char expected_tag)
190 {
191 if (index < 0
192 || index > pool_count
193 || tags[index] != expected_tag)
194 throw_class_format_error ("erroneous constant pool tag");
195 }
196
197 _Jv_ClassReader (jclass klass, jbyteArray data, jint offset, jint length)
198 {
199 if (klass == 0 || length < 0 || offset+length > data->length)
200 throw_internal_error ("arguments to _Jv_DefineClass");
201
202 verify = true;
203 bytes = (unsigned char*) (elements (data)+offset);
204 len = length;
205 pos = 0;
206 def = (_Jv_InterpClass*) klass;
207 }
208
209 /** and here goes the parser members defined out-of-line */
210 void parse ();
211 void read_constpool ();
212 void prepare_pool_entry (int index, unsigned char tag);
213 void read_fields ();
214 void read_methods ();
215 void read_one_class_attribute ();
216 void read_one_method_attribute (int method);
217 void read_one_code_attribute (int method);
218 void read_one_field_attribute (int field);
219
220 /** check an utf8 entry, without creating a Utf8Const object */
221 bool is_attribute_name (int index, char *name);
222
223 /** here goes the class-loader members defined out-of-line */
224 void handleConstantPool ();
225 void handleClassBegin (int, int, int);
226 void handleInterfacesBegin (int);
227 void handleInterface (int, int);
228 void handleFieldsBegin (int);
229 void handleField (int, int, int, int);
230 void handleFieldsEnd ();
231 void handleConstantValueAttribute (int,int);
232 void handleMethodsBegin (int);
233 void handleMethod (int, int, int, int);
234 void handleMethodsEnd ();
235 void handleCodeAttribute (int, int, int, int, int, int);
236 void handleExceptionTableEntry (int, int, int, int, int, int);
237
238 void checkExtends (jclass sub, jclass super);
239 void checkImplements (jclass sub, jclass super);
240
241 /*
242 * FIXME: we should keep a hash table of utf8-strings, since many will
243 * be the same. It's a little tricky, however, because the hash table
244 * needs to interact gracefully with the garbage collector. Much
245 * memory is to be saved by this, however! perhaps the improvement
246 * could be implemented in prims.cc (_Jv_makeUtf8Const), since it
247 * computes the hash value anyway.
248 */
249 };
250
251 /* This is used for the isJavaIdentifierStart & isJavaIdentifierPart
252 methods, so we avoid doing _Jv_InitClass all the time */
253
254 static const java::lang::Character *character = 0;
255 static void prepare_character ();
256
257 void
258 _Jv_DefineClass (jclass klass, jbyteArray data, jint offset, jint length)
259 {
260 if (character == 0)
261 prepare_character ();
262
263 _Jv_ClassReader reader (klass, data, offset, length);
264 reader.parse();
265
266 /* that's it! */
267 }
268
269 /** put it after _Jv_DefineClass, so it doesn't get inlined */
270 static void prepare_character ()
271 {
272 character = new java::lang::Character ('!');
273 }
274
275 \f
276 /** This section defines the parsing/scanning of the class data */
277
278 void
279 _Jv_ClassReader::parse ()
280 {
281 int magic = read4 ();
282
283 /* FIXME: Decide which range of version numbers to allow */
284
285 /* int minor_version = */ read2u ();
286 /* int major_verson = */ read2u ();
287
288 if (magic != (int) 0xCAFEBABE)
289 throw_class_format_error ("bad magic number");
290
291 pool_count = read2u ();
292
293 read_constpool ();
294
295 int access_flags = read2u ();
296 int this_class = read2u ();
297 int super_class = read2u ();
298
299 check_tag (this_class, JV_CONSTANT_Class);
300 if (super_class != 0)
301 check_tag (super_class, JV_CONSTANT_Class);
302
303 handleClassBegin (access_flags, this_class, super_class);
304
305 int interfaces_count = read2u ();
306
307 handleInterfacesBegin (interfaces_count);
308
309 for (int i = 0; i < interfaces_count; i++)
310 {
311 int iface = read2u ();
312 check_tag (iface, JV_CONSTANT_Class);
313 handleInterface (i, iface);
314 }
315
316 read_fields ();
317 read_methods ();
318
319 int attributes_count = read2u ();
320
321 for (int i = 0; i < attributes_count; i++)
322 {
323 read_one_class_attribute ();
324 }
325
326 if (pos != len)
327 throw_class_format_error ("unused data before end of file");
328
329 // tell everyone we're done.
330 def->state = JV_STATE_LOADED;
331 def->notifyAll ();
332
333 }
334
335 void _Jv_ClassReader::read_constpool ()
336 {
337 tags = (unsigned char*) _Jv_AllocBytesChecked (pool_count);
338 offsets = (unsigned int *) _Jv_AllocBytesChecked (sizeof (int)
339 * pool_count) ;
340
341 /** first, we scan the constant pool, collecting tags and offsets */
342 tags[0] = JV_CONSTANT_Undefined;
343 offsets[0] = pos;
344 for (int c = 1; c < pool_count; c++)
345 {
346 tags[c] = read1u ();
347 offsets[c] = pos;
348
349 switch (tags[c])
350 {
351 case JV_CONSTANT_String:
352 case JV_CONSTANT_Class:
353 skip (2);
354 break;
355
356 case JV_CONSTANT_Fieldref:
357 case JV_CONSTANT_Methodref:
358 case JV_CONSTANT_InterfaceMethodref:
359 case JV_CONSTANT_NameAndType:
360 case JV_CONSTANT_Integer:
361 case JV_CONSTANT_Float:
362 skip (4);
363 break;
364
365 case JV_CONSTANT_Double:
366 case JV_CONSTANT_Long:
367 skip (8);
368 tags[++c] = JV_CONSTANT_Undefined;
369 break;
370
371 case JV_CONSTANT_Utf8:
372 {
373 int len = read2u ();
374 skip (len);
375 }
376 break;
377
378 case JV_CONSTANT_Unicode:
379 throw_class_format_error ("unicode not supported");
380 break;
381
382 default:
383 throw_class_format_error ("erroneous constant pool tag");
384 }
385 }
386
387 handleConstantPool ();
388 }
389
390
391 void _Jv_ClassReader::read_fields ()
392 {
393 int fields_count = read2u ();
394 handleFieldsBegin (fields_count);
395
396 for (int i = 0; i < fields_count; i++)
397 {
398 int access_flags = read2u ();
399 int name_index = read2u ();
400 int descriptor_index = read2u ();
401 int attributes_count = read2u ();
402
403 check_tag (name_index, JV_CONSTANT_Utf8);
404 prepare_pool_entry (name_index, JV_CONSTANT_Utf8);
405
406 check_tag (descriptor_index, JV_CONSTANT_Utf8);
407 prepare_pool_entry (descriptor_index, JV_CONSTANT_Utf8);
408
409 handleField (i, access_flags, name_index, descriptor_index);
410
411 for (int j = 0; j < attributes_count; j++)
412 {
413 read_one_field_attribute (i);
414 }
415 }
416
417 handleFieldsEnd ();
418 }
419
420 bool
421 _Jv_ClassReader::is_attribute_name (int index, char *name)
422 {
423 check_tag (index, JV_CONSTANT_Utf8);
424 int len = get2u (bytes+offsets[index]);
425 if (len != (int) strlen (name))
426 return false;
427 else
428 return !memcmp (bytes+offsets[index]+2, name, len);
429 }
430
431 void _Jv_ClassReader::read_one_field_attribute (int field_index)
432 {
433 int name = read2u ();
434 int length = read4 ();
435
436 if (is_attribute_name (name, "ConstantValue"))
437 {
438 int cv = read2u ();
439
440 if (cv < pool_count
441 && cv > 0
442 && (tags[cv] == JV_CONSTANT_Integer
443 || tags[cv] == JV_CONSTANT_Float
444 || tags[cv] == JV_CONSTANT_Long
445 || tags[cv] == JV_CONSTANT_Double
446 || tags[cv] == JV_CONSTANT_String))
447 {
448 handleConstantValueAttribute (field_index, cv);
449 }
450 else
451 {
452 throw_class_format_error ("erroneous ConstantValue attribute");
453 }
454
455 if (length != 2)
456 throw_class_format_error ("erroneous ConstantValue attribute");
457 }
458
459 else
460 {
461 skip (length);
462 }
463 }
464
465 void _Jv_ClassReader::read_methods ()
466 {
467 int methods_count = read2u ();
468
469 handleMethodsBegin (methods_count);
470
471 for (int i = 0; i < methods_count; i++)
472 {
473 int access_flags = read2u ();
474 int name_index = read2u ();
475 int descriptor_index = read2u ();
476 int attributes_count = read2u ();
477
478 check_tag (name_index, JV_CONSTANT_Utf8);
479 prepare_pool_entry (descriptor_index, JV_CONSTANT_Utf8);
480
481 check_tag (name_index, JV_CONSTANT_Utf8);
482 prepare_pool_entry (descriptor_index, JV_CONSTANT_Utf8);
483
484 handleMethod (i, access_flags, name_index,
485 descriptor_index);
486
487 for (int j = 0; j < attributes_count; j++)
488 {
489 read_one_method_attribute (i);
490 }
491 }
492
493 handleMethodsEnd ();
494 }
495
496 void _Jv_ClassReader::read_one_method_attribute (int method_index)
497 {
498 int name = read2u ();
499 int length = read4 ();
500
501 if (is_attribute_name (name, "Exceptions"))
502 {
503 /* we ignore this for now */
504 skip (length);
505 }
506
507 else if (is_attribute_name (name, "Code"))
508 {
509 int start_off = pos;
510 int max_stack = read2u ();
511 int max_locals = read2u ();
512 int code_length = read4 ();
513
514 int code_start = pos;
515 skip (code_length);
516 int exception_table_length = read2u ();
517
518 handleCodeAttribute (method_index,
519 max_stack, max_locals,
520 code_start, code_length,
521 exception_table_length);
522
523
524 for (int i = 0; i < exception_table_length; i++)
525 {
526 int start_pc = read2u ();
527 int end_pc = read2u ();
528 int handler_pc = read2u ();
529 int catch_type = read2u ();
530
531 if (start_pc > end_pc
532 || start_pc < 0
533 || end_pc >= code_length
534 || handler_pc >= code_length)
535 throw_class_format_error ("erroneous exception handler info");
536
537 if (! (tags[catch_type] == JV_CONSTANT_Class
538 || tags[catch_type] == 0))
539 {
540 throw_class_format_error ("erroneous exception handler info");
541 }
542
543 handleExceptionTableEntry (method_index,
544 i,
545 start_pc,
546 end_pc,
547 handler_pc,
548 catch_type);
549
550 }
551
552 int attributes_count = read2u ();
553
554 for (int i = 0; i < attributes_count; i++)
555 {
556 read_one_code_attribute (method_index);
557 }
558
559 if ((pos - start_off) != length)
560 throw_class_format_error ("code attribute too short");
561 }
562
563 else
564 {
565 /* ignore unknown attributes */
566 skip (length);
567 }
568 }
569
570 void _Jv_ClassReader::read_one_code_attribute (int /*method*/)
571 {
572 /* ignore for now, ... later we may want to pick up
573 line number information, for debugging purposes;
574 in fact, the whole debugger issue is open! */
575
576 /* int name = */ read2u ();
577 int length = read4 ();
578 skip (length);
579
580 }
581
582 void _Jv_ClassReader::read_one_class_attribute ()
583 {
584 /* we also ignore the class attributes, ...
585 some day we'll add inner-classes support. */
586
587 /* int name = */ read2u ();
588 int length = read4 ();
589 skip (length);
590 }
591
592
593
594 \f
595 /* this section defines the semantic actions of the parser */
596
597 void _Jv_ClassReader::handleConstantPool ()
598 {
599 /** now, we actually define the class' constant pool */
600
601 // the pool is scanned explicitly by the collector
602 jbyte *pool_tags = (jbyte*) _Jv_AllocBytesChecked (pool_count);
603 _Jv_word *pool_data
604 = (_Jv_word*) _Jv_AllocBytesChecked (pool_count * sizeof (_Jv_word));
605
606 def->constants.tags = pool_tags;
607 def->constants.data = pool_data;
608 def->constants.size = pool_count;
609
610 // Here we make a pass to collect the strings! We do this, because
611 // internally in the GCJ runtime, classes are encoded with .'s not /'s.
612 // Therefore, we first collect the strings, and then translate the rest
613 // of the utf8-entries (thus not representing strings) from /-notation
614 // to .-notation.
615 for (int i = 1; i < pool_count; i++)
616 {
617 if (tags[i] == JV_CONSTANT_String)
618 {
619 unsigned char* str_data = bytes + offsets [i];
620 int utf_index = get2u (str_data);
621 check_tag (utf_index, JV_CONSTANT_Utf8);
622 unsigned char *utf_data = bytes + offsets[utf_index];
623 int len = get2u (utf_data);
624 pool_data[i].utf8 = _Jv_makeUtf8Const ((char*)(utf_data+2), len);
625 pool_tags[i] = JV_CONSTANT_String;
626 }
627 else
628 {
629 pool_tags[i] = JV_CONSTANT_Undefined;
630 }
631 }
632
633 // and now, we scan everything else but strings & utf8-entries. This
634 // leaves out those utf8-entries which are not used; which will be left
635 // with a tag of JV_CONSTANT_Undefined in the class definition.
636 for (int index = 1; index < pool_count; index++)
637 {
638 switch (tags[index])
639 {
640 case JV_CONSTANT_Undefined:
641 case JV_CONSTANT_String:
642 case JV_CONSTANT_Utf8:
643 continue;
644
645 default:
646 prepare_pool_entry (index, tags[index]);
647 }
648 }
649
650 }
651
652 /* this is a recursive procedure, which will prepare pool entries as needed.
653 Which is how we avoid initializing those entries which go unused. */
654 void
655 _Jv_ClassReader::prepare_pool_entry (int index, unsigned char this_tag)
656 {
657 /* these two, pool_data and pool_tags, point into the class
658 structure we are currently defining */
659
660 unsigned char *pool_tags = (unsigned char*) def->constants.tags;
661 _Jv_word *pool_data = def->constants.data;
662
663 /* this entry was already prepared */
664 if (pool_tags[index] == this_tag)
665 return;
666
667 /* this_data points to the constant-pool information for the current
668 constant-pool entry */
669
670 unsigned char *this_data = bytes + offsets[index];
671
672 switch (this_tag)
673 {
674 case JV_CONSTANT_Utf8:
675 {
676 // If we came here, it is because some other tag needs this
677 // utf8-entry for type information! Thus, we translate /'s to .'s in
678 // order to accomondate gcj's internal representation.
679
680 int len = get2u (this_data);
681 char *buffer = (char*) alloca (len);
682 char *s = ((char*) this_data)+2;
683
684 /* FIXME: avoid using a buffer here */
685 for (int i = 0; i < len; i++)
686 {
687 if (s[i] == '/')
688 buffer[i] = '.';
689 else
690 buffer[i] = (char) s[i];
691 }
692
693 pool_data[index].utf8 = _Jv_makeUtf8Const (buffer, len);
694 pool_tags[index] = JV_CONSTANT_Utf8;
695 }
696 break;
697
698 case JV_CONSTANT_Class:
699 {
700 int utf_index = get2u (this_data);
701 check_tag (utf_index, JV_CONSTANT_Utf8);
702 prepare_pool_entry (utf_index, JV_CONSTANT_Utf8);
703
704 if (verify)
705 _Jv_VerifyClassName (pool_data[utf_index].utf8);
706
707 pool_data[index].utf8 = pool_data[utf_index].utf8;
708 pool_tags[index] = JV_CONSTANT_Class;
709 }
710 break;
711
712 case JV_CONSTANT_String:
713 // already handled before...
714 break;
715
716 case JV_CONSTANT_Fieldref:
717 case JV_CONSTANT_Methodref:
718 case JV_CONSTANT_InterfaceMethodref:
719 {
720 int class_index = get2u (this_data);
721 int nat_index = get2u (this_data+2);
722
723 check_tag (class_index, JV_CONSTANT_Class);
724 prepare_pool_entry (class_index, JV_CONSTANT_Class);
725
726 check_tag (nat_index, JV_CONSTANT_NameAndType);
727 prepare_pool_entry (nat_index, JV_CONSTANT_NameAndType);
728
729 // here, verify the signature and identifier name
730 if (verify)
731 {
732 _Jv_ushort name_index, type_index;
733 _Jv_loadIndexes (&pool_data[nat_index],
734 name_index, type_index);
735
736 if (this_tag == JV_CONSTANT_Fieldref)
737 _Jv_VerifyFieldSignature (pool_data[type_index].utf8);
738 else
739 _Jv_VerifyMethodSignature (pool_data[type_index].utf8);
740
741 _Jv_Utf8Const* name = pool_data[name_index].utf8;
742
743 if (this_tag != JV_CONSTANT_Fieldref
744 && ( _Jv_equalUtf8Consts (name, clinit_name)
745 || _Jv_equalUtf8Consts (name, init_name)))
746 /* ignore */;
747 else
748 _Jv_VerifyIdentifier (pool_data[name_index].utf8);
749 }
750
751 _Jv_storeIndexes (&pool_data[index], class_index, nat_index);
752 pool_tags[index] = this_tag;
753 }
754 break;
755
756 case JV_CONSTANT_NameAndType:
757 {
758 _Jv_ushort name_index = get2u (this_data);
759 _Jv_ushort type_index = get2u (this_data+2);
760
761 check_tag (name_index, JV_CONSTANT_Utf8);
762 prepare_pool_entry (name_index, JV_CONSTANT_Utf8);
763
764 check_tag (type_index, JV_CONSTANT_Utf8);
765 prepare_pool_entry (type_index, JV_CONSTANT_Utf8);
766
767 _Jv_storeIndexes (&pool_data[index], name_index, type_index);
768 pool_tags[index] = JV_CONSTANT_NameAndType;
769 }
770 break;
771
772 case JV_CONSTANT_Float:
773 {
774 jfloat f = int_bits_to_float ((jint) get4 (this_data));
775 _Jv_storeFloat (&pool_data[index], f);
776 pool_tags[index] = JV_CONSTANT_Float;
777 }
778 break;
779
780 case JV_CONSTANT_Integer:
781 {
782 int i = get4 (this_data);
783 _Jv_storeInt (&pool_data[index], i);
784 pool_tags[index] = JV_CONSTANT_Integer;
785 }
786 break;
787
788 case JV_CONSTANT_Double:
789 {
790 jdouble d = long_bits_to_double ((jlong) get8 (this_data));
791 _Jv_storeDouble (&pool_data[index], d);
792 pool_tags[index] = JV_CONSTANT_Double;
793 }
794 break;
795
796 case JV_CONSTANT_Long:
797 {
798 jlong i = get8 (this_data);
799 _Jv_storeLong (&pool_data[index], i);
800 pool_tags[index] = JV_CONSTANT_Long;
801 }
802 break;
803
804 default:
805 throw_class_format_error ("erroneous constant pool tag");
806 }
807 }
808
809
810 void
811 _Jv_ClassReader::handleClassBegin
812 (int access_flags, int this_class, int super_class)
813 {
814 using namespace java::lang::reflect;
815
816 unsigned char *pool_tags = (unsigned char*) def->constants.tags;
817 _Jv_word *pool_data = def->constants.data;
818
819 check_tag (this_class, JV_CONSTANT_Class);
820 _Jv_Utf8Const *loadedName = pool_data[this_class].utf8;
821
822 // was ClassLoader.defineClass called with an expected class name?
823 if (def->name == 0)
824 {
825 jclass orig = _Jv_FindClassInCache (loadedName, def->loader);
826
827 if (orig == 0)
828 {
829 def->name = loadedName;
830 }
831 else
832 {
833 jstring msg = JvNewStringUTF ("anonymous "
834 "class data denotes "
835 "existing class ");
836 msg = msg->concat (orig->getName ());
837
838 throw_no_class_def_found_error (msg);
839 }
840 }
841
842 // assert that the loaded class has the expected name, 5.3.5
843 else if (! _Jv_equalUtf8Consts (loadedName, def->name))
844 {
845 jstring msg = JvNewStringUTF ("loaded class ");
846 msg = msg->concat (def->getName ());
847 msg = msg->concat (_Jv_NewStringUTF (" was in fact named "));
848 jstring klass_name = _Jv_NewStringUTF (loadedName->data);
849 msg = msg->concat (klass_name);
850
851 throw_no_class_def_found_error (msg);
852 }
853
854 def->accflags = access_flags;
855 pool_data[this_class].clazz = def;
856 pool_tags[this_class] = JV_CONSTANT_ResolvedClass;
857
858 if (super_class == 0)
859 {
860 // interfaces have java.lang.Object as super.
861 if (access_flags & Modifier::INTERFACE)
862 {
863 def->superclass = (jclass)&java::lang::Class::class$;
864 }
865
866 // FIXME: Consider this carefully!
867 else if (!_Jv_equalUtf8Consts (def->name,
868 java::lang::Class::class$.name))
869 {
870 throw_no_class_def_found_error ("loading java.lang.Object");
871 }
872 }
873
874 // In the pre-loading state, it can be looked up in the
875 // cache only by this thread! This allows the super-class
876 // to include references to this class.
877
878 def->state = JV_STATE_PRELOADING;
879 _Jv_RegisterClass (def);
880
881 if (super_class != 0)
882 {
883 // load the super class
884 check_tag (super_class, JV_CONSTANT_Class);
885 _Jv_Utf8Const* super_name = pool_data[super_class].utf8;
886
887 // load the super class using our defining loader
888 jclass the_super = _Jv_FindClass (super_name,
889 def->loader);
890
891 // This will establish that we are allowed to be a subclass,
892 // and check for class circularity error
893 checkExtends (def, the_super);
894
895 def->superclass = the_super;
896 pool_data[super_class].clazz = the_super;
897 pool_tags[super_class] = JV_CONSTANT_ResolvedClass;
898 }
899
900 // now we've come past the circularity problem, we can
901 // now say that we're loading...
902
903 def->state = JV_STATE_LOADING;
904 def->notifyAll ();
905 }
906
907 ///// implements the checks described in sect. 5.3.5.3
908 void
909 _Jv_ClassReader::checkExtends (jclass sub, jclass super)
910 {
911 using namespace java::lang::reflect;
912
913 // having an interface or a final class as a superclass is no good
914 if ((super->accflags & (Modifier::INTERFACE | Modifier::FINAL)) != 0)
915 {
916 throw_incompatible_class_change_error (sub->getName ());
917 }
918
919 // if the super class is not public, we need to check some more
920 if ((super->accflags & Modifier::PUBLIC) == 0)
921 {
922 // With package scope, the classes must have the same
923 // class loader.
924 if ( sub->loader != super->loader
925 || !_Jv_ClassNameSamePackage (sub->name, super->name))
926 {
927 throw_incompatible_class_change_error (sub->getName ());
928 }
929 }
930
931 for (; super != 0; super = super->superclass)
932 {
933 if (super == sub)
934 throw_class_circularity_error (sub->getName ());
935 }
936 }
937
938
939
940 void _Jv_ClassReader::handleInterfacesBegin (int count)
941 {
942 def->interfaces = (jclass*) _Jv_AllocBytesChecked (count*sizeof (jclass));
943 def->interface_count = count;
944 }
945
946 void _Jv_ClassReader::handleInterface (int if_number, int offset)
947 {
948 _Jv_word * pool_data = def->constants.data;
949 unsigned char * pool_tags = (unsigned char*) def->constants.tags;
950
951 jclass the_interface;
952
953 if (pool_tags[offset] == JV_CONSTANT_Class)
954 {
955 _Jv_Utf8Const* name = pool_data[offset].utf8;
956 the_interface = _Jv_FindClass (name, def->loader);
957 }
958 else if (pool_tags[offset] == JV_CONSTANT_ResolvedClass)
959 {
960 the_interface = pool_data[offset].clazz;
961 }
962 else
963 {
964 throw_no_class_def_found_error ("erroneous constant pool tag");
965 }
966
967 // checks the validity of the_interface, and that we are in fact
968 // allowed to implement that interface.
969 checkImplements (def, the_interface);
970
971 pool_data[offset].clazz = the_interface;
972 pool_tags[offset] = JV_CONSTANT_ResolvedClass;
973
974 def->interfaces[if_number] = the_interface;
975 }
976
977 void
978 _Jv_ClassReader::checkImplements (jclass sub, jclass super)
979 {
980 using namespace java::lang::reflect;
981
982 // well, it *must* be an interface
983 if ((super->accflags & Modifier::INTERFACE) == 0)
984 {
985 throw_incompatible_class_change_error (sub->getName ());
986 }
987
988 // if it has package scope, it must also be defined by the
989 // same loader.
990 if ((super->accflags & Modifier::PUBLIC) == 0)
991 {
992 if ( sub->loader != super->loader
993 || !_Jv_ClassNameSamePackage (sub->name, super->name))
994 {
995 throw_incompatible_class_change_error (sub->getName ());
996 }
997 }
998
999 // FIXME: add interface circularity check here
1000 if (sub == super)
1001 {
1002 throw_class_circularity_error (sub->getName ());
1003 }
1004 }
1005
1006 void _Jv_ClassReader::handleFieldsBegin (int count)
1007 {
1008 def->fields = (_Jv_Field*)
1009 _Jv_AllocBytesChecked (count * sizeof (_Jv_Field));
1010 def->field_count = count;
1011 def->field_initializers = (_Jv_ushort*)
1012 _Jv_AllocBytesChecked (count * sizeof (_Jv_ushort));
1013 for (int i = 0; i < count; i++)
1014 def->field_initializers[i] = (_Jv_ushort) 0;
1015 }
1016
1017 void _Jv_ClassReader::handleField (int field_no,
1018 int flags,
1019 int name,
1020 int desc)
1021 {
1022 using namespace java::lang::reflect;
1023
1024 _Jv_word *pool_data = def->constants.data;
1025
1026 _Jv_Field *field = &def->fields[field_no];
1027 _Jv_Utf8Const *field_name = pool_data[name].utf8;
1028
1029 #ifndef COMPACT_FIELDS
1030 field->name = field_name;
1031 #else
1032 field->nameIndex = name;
1033 #endif
1034
1035 if (verify)
1036 _Jv_VerifyIdentifier (field_name);
1037
1038 // ignore flags we don't know about.
1039 field->flags = flags & Modifier::ALL_FLAGS;
1040
1041 if (verify)
1042 {
1043 if (field->flags & (Modifier::SYNCHRONIZED
1044 | Modifier::NATIVE
1045 | Modifier::INTERFACE
1046 | Modifier::ABSTRACT))
1047 throw_class_format_error ("erroneous field access flags");
1048
1049 if (1 < ( ((field->flags & Modifier::PUBLIC) ? 1 : 0)
1050 +((field->flags & Modifier::PRIVATE) ? 1 : 0)
1051 +((field->flags & Modifier::PROTECTED) ? 1 : 0)))
1052 throw_class_format_error ("erroneous field access flags");
1053 }
1054
1055 _Jv_Utf8Const* sig = pool_data[desc].utf8;
1056
1057 if (verify)
1058 _Jv_VerifyFieldSignature (sig);
1059
1060 // field->type is really a jclass, but while it is still
1061 // unresolved we keep an _Jv_Utf8Const* instead.
1062 field->type = (jclass) sig;
1063 field->flags |= _Jv_FIELD_UNRESOLVED_FLAG;
1064 field->u.boffset = 0;
1065 }
1066
1067
1068 void _Jv_ClassReader::handleConstantValueAttribute (int field_index,
1069 int value)
1070 {
1071 using namespace java::lang::reflect;
1072
1073 _Jv_Field *field = &def->fields[field_index];
1074
1075 if ((field->flags & (Modifier::STATIC
1076 | Modifier::FINAL
1077 | Modifier::PRIVATE)) == 0)
1078 {
1079 // Ignore, as per vmspec #4.7.2
1080 return;
1081 }
1082
1083 // do not allow multiple constant fields!
1084 if (field->flags & _Jv_FIELD_CONSTANT_VALUE)
1085 throw_class_format_error ("field has multiple ConstantValue attributes");
1086
1087 field->flags |= _Jv_FIELD_CONSTANT_VALUE;
1088 def->field_initializers[field_index] = value;
1089
1090 /* type check the initializer */
1091
1092 if (value <= 0 || value >= pool_count)
1093 throw_class_format_error ("erroneous ConstantValue attribute");
1094
1095 /* FIXME: do the rest */
1096 }
1097
1098 void _Jv_ClassReader::handleFieldsEnd ()
1099 {
1100 using namespace java::lang::reflect;
1101
1102 // We need to reorganize the fields so that the static ones are first,
1103 // to conform to GCJ class layout.
1104
1105 int low = 0;
1106 int high = def->field_count-1;
1107 _Jv_Field *fields = def->fields;
1108 _Jv_ushort *inits = def->field_initializers;
1109
1110 // this is kind of a raw version of quicksort.
1111 while (low < high)
1112 {
1113 // go forward on low, while it's a static
1114 while (low < high && (fields[low].flags & Modifier::STATIC) != 0)
1115 low++;
1116
1117 // go backwards on high, while it's a non-static
1118 while (low < high && (fields[high].flags & Modifier::STATIC) == 0)
1119 high--;
1120
1121 if (low==high)
1122 break;
1123
1124 _Jv_Field tmp = fields[low];
1125 _Jv_ushort itmp = inits[low];
1126
1127 fields[low] = fields[high];
1128 inits[low] = inits[high];
1129
1130 fields[high] = tmp;
1131 inits[high] = itmp;
1132
1133 high -= 1;
1134 low += 1;
1135 }
1136
1137 if ((fields[low].flags & Modifier::STATIC) != 0)
1138 low += 1;
1139
1140 def->static_field_count = low;
1141 }
1142
1143
1144
1145 void
1146 _Jv_ClassReader::handleMethodsBegin (int count)
1147 {
1148 def->methods = (_Jv_Method*)
1149 _Jv_AllocBytesChecked (sizeof (_Jv_Method)*count);
1150
1151 def->interpreted_methods
1152 = (_Jv_MethodBase **) _Jv_AllocBytesChecked (sizeof (_Jv_MethodBase *)
1153 * count);
1154
1155 for (int i = 0; i < count; i++)
1156 def->interpreted_methods[i] = 0;
1157
1158 def->method_count = count;
1159 }
1160
1161
1162 void _Jv_ClassReader::handleMethod
1163 (int mth_index, int accflags, int name, int desc)
1164 {
1165 using namespace java::lang::reflect;
1166
1167 _Jv_word *pool_data = def->constants.data;
1168 _Jv_Method *method = &def->methods[mth_index];
1169
1170 check_tag (name, JV_CONSTANT_Utf8);
1171 prepare_pool_entry (name, JV_CONSTANT_Utf8);
1172 method->name = pool_data[name].utf8;
1173
1174 check_tag (desc, JV_CONSTANT_Utf8);
1175 prepare_pool_entry (desc, JV_CONSTANT_Utf8);
1176 method->signature = pool_data[desc].utf8;
1177
1178 // ignore unknown flags
1179 method->accflags = accflags & Modifier::ALL_FLAGS;
1180
1181 // intialize...
1182 method->ncode = 0;
1183
1184 if (verify)
1185 {
1186 if (_Jv_equalUtf8Consts (method->name, clinit_name)
1187 || _Jv_equalUtf8Consts (method->name, init_name))
1188 /* ignore */;
1189 else
1190 _Jv_VerifyIdentifier (method->name);
1191
1192 _Jv_VerifyMethodSignature (method->signature);
1193
1194 if (method->accflags & (Modifier::VOLATILE
1195 | Modifier::TRANSIENT
1196 | Modifier::INTERFACE))
1197 throw_class_format_error ("erroneous method access flags");
1198
1199 if (1 < ( ((method->accflags & Modifier::PUBLIC) ? 1 : 0)
1200 +((method->accflags & Modifier::PRIVATE) ? 1 : 0)
1201 +((method->accflags & Modifier::PROTECTED) ? 1 : 0)))
1202 throw_class_format_error ("erroneous method access flags");
1203 }
1204 }
1205
1206 void _Jv_ClassReader::handleCodeAttribute
1207 (int method_index, int max_stack, int max_locals,
1208 int code_start, int code_length, int exc_table_length)
1209 {
1210 int size = _Jv_InterpMethod::size (exc_table_length, code_length);
1211 _Jv_InterpMethod *method =
1212 (_Jv_InterpMethod*) (_Jv_AllocBytesChecked (size));
1213
1214 method->max_stack = max_stack;
1215 method->max_locals = max_locals;
1216 method->code_length = code_length;
1217 method->exc_count = exc_table_length;
1218 method->defining_class = def;
1219 method->self = &def->methods[method_index];
1220
1221 // grab the byte code!
1222 memcpy ((void*) method->bytecode (),
1223 (void*) (bytes+code_start),
1224 code_length);
1225
1226 def->interpreted_methods[method_index] = method;
1227
1228 /* that's all we do for now */
1229 }
1230
1231 void _Jv_ClassReader::handleExceptionTableEntry
1232 (int method_index, int exc_index,
1233 int start_pc, int end_pc, int handler_pc, int catch_type)
1234 {
1235 _Jv_InterpMethod *method = reinterpret_cast<_Jv_InterpMethod *>
1236 (def->interpreted_methods[method_index]);
1237 _Jv_InterpException *exc = method->exceptions ();
1238
1239 exc[exc_index].start_pc = start_pc;
1240 exc[exc_index].end_pc = end_pc;
1241 exc[exc_index].handler_pc = handler_pc;
1242 exc[exc_index].handler_type = catch_type;
1243 }
1244
1245 void _Jv_ClassReader::handleMethodsEnd ()
1246 {
1247 using namespace java::lang::reflect;
1248
1249 for (int i = 0; i < def->method_count; i++)
1250 {
1251 _Jv_Method *method = &def->methods[i];
1252 if ((method->accflags & Modifier::NATIVE) != 0)
1253 {
1254 if (def->interpreted_methods[i] != 0)
1255 throw_class_format_error ("code provided for native method");
1256 else
1257 {
1258 _Jv_JNIMethod *m = (_Jv_JNIMethod *)
1259 _Jv_AllocBytesChecked (sizeof (_Jv_JNIMethod));
1260 m->defining_class = def;
1261 m->self = method;
1262 m->function = NULL;
1263 def->interpreted_methods[i] = m;
1264 }
1265 }
1266 else if ((method->accflags & Modifier::ABSTRACT) != 0)
1267 {
1268 if (def->interpreted_methods[i] != 0)
1269 throw_class_format_error ("code provided for abstract method");
1270 }
1271 else
1272 {
1273 if (def->interpreted_methods[i] == 0)
1274 throw_class_format_error ("method with no code");
1275 }
1276 }
1277
1278 }
1279
1280 \f
1281 /** This section takes care of verifying integrity of identifiers,
1282 signatures, field ddescriptors, and class names */
1283
1284 #define UTF8_PEEK(PTR, LIMIT) \
1285 ({ unsigned char* xxkeep = (PTR); \
1286 int xxch = UTF8_GET(PTR,LIMIT); \
1287 PTR = xxkeep; xxch; })
1288
1289 /* verify one element of a type descriptor or signature */
1290 static unsigned char*
1291 _Jv_VerifyOne (unsigned char* ptr, unsigned char* limit, bool void_ok)
1292 {
1293 if (ptr >= limit)
1294 return 0;
1295
1296 int ch = UTF8_GET (ptr, limit);
1297
1298 switch (ch)
1299 {
1300 case 'V':
1301 if (! void_ok) return 0;
1302
1303 case 'S': case 'B': case 'I': case 'J':
1304 case 'Z': case 'C': case 'F': case 'D':
1305 break;
1306
1307 case 'L':
1308 {
1309 unsigned char *start = ptr, *end;
1310 do {
1311 if (ptr > limit)
1312 return 0;
1313
1314 end = ptr;
1315
1316 if ((ch = UTF8_GET (ptr, limit)) == -1)
1317 return 0;
1318
1319 } while (ch != ';');
1320 _Jv_VerifyClassName (start, (unsigned short) (end-start));
1321 }
1322 break;
1323
1324 case '[':
1325 return _Jv_VerifyOne (ptr, limit, false);
1326 break;
1327
1328 default:
1329 return 0;
1330 }
1331
1332 return ptr;
1333
1334 }
1335
1336
1337 /** verification and loading procedures **/
1338
1339 void
1340 _Jv_VerifyFieldSignature (_Jv_Utf8Const*sig)
1341 {
1342 unsigned char* ptr = (unsigned char*) sig->data;
1343 unsigned char* limit = ptr + sig->length;
1344
1345 ptr = _Jv_VerifyOne (ptr, limit, false);
1346
1347 if (ptr != limit)
1348 throw_class_format_error ("erroneous type descriptor");
1349 }
1350
1351 void
1352 _Jv_VerifyMethodSignature (_Jv_Utf8Const*sig)
1353 {
1354 unsigned char* ptr = (unsigned char*) sig->data;
1355 unsigned char* limit = ptr + sig->length;
1356
1357 if (ptr == limit)
1358 throw_class_format_error ("erroneous type descriptor");
1359
1360 if (UTF8_GET(ptr,limit) != '(')
1361 throw_class_format_error ("erroneous type descriptor");
1362
1363 while (ptr && UTF8_PEEK (ptr, limit) != ')')
1364 ptr = _Jv_VerifyOne (ptr, limit, false);
1365
1366 if (UTF8_GET (ptr, limit) != ')')
1367 throw_class_format_error ("erroneous type descriptor");
1368
1369 // get the return type
1370 ptr = _Jv_VerifyOne (ptr, limit, true);
1371
1372 if (ptr != limit)
1373 throw_class_format_error ("erroneous type descriptor");
1374
1375 return;
1376
1377 }
1378
1379 /* we try to avoid calling the Character methods all the time,
1380 in fact, they will only be called for non-standard things */
1381
1382 static __inline__ int
1383 is_identifier_start (int c)
1384 {
1385 unsigned int ch = (unsigned)c;
1386
1387 if ((ch - 0x41U) < 29U) /* A ... Z */
1388 return 1;
1389 if ((ch - 0x61U) < 29U) /* a ... z */
1390 return 1;
1391 if (ch == 0x5FU) /* _ */
1392 return 1;
1393
1394 return character->isJavaIdentifierStart ((jchar) ch);
1395 }
1396
1397 static __inline__ int
1398 is_identifier_part (int c)
1399 {
1400 unsigned int ch = (unsigned)c;
1401
1402 if ((ch - 0x41U) < 29U) /* A ... Z */
1403 return 1;
1404 if ((ch - 0x61U) < 29U) /* a ... z */
1405 return 1;
1406 if ((ch - 0x30) < 10U) /* 0 .. 9 */
1407 return 1;
1408 if (ch == 0x5FU || ch == 0x24U) /* _ $ */
1409 return 1;
1410
1411 return character->isJavaIdentifierStart ((jchar) ch);
1412 }
1413
1414 void
1415 _Jv_VerifyIdentifier (_Jv_Utf8Const* name)
1416 {
1417 unsigned char *ptr = (unsigned char*) name->data;
1418 unsigned char *limit = ptr + name->length;
1419 int ch;
1420
1421 if ((ch = UTF8_GET (ptr, limit))==-1
1422 || ! is_identifier_start (ch))
1423 throw_class_format_error ("erroneous identifier");
1424
1425 while (ptr != limit)
1426 {
1427 if ((ch = UTF8_GET (ptr, limit))==-1
1428 || ! is_identifier_part (ch))
1429 throw_class_format_error ("erroneous identifier");
1430 }
1431 }
1432
1433
1434 void
1435 _Jv_VerifyClassName (unsigned char* ptr, _Jv_ushort length)
1436 {
1437 unsigned char *limit = ptr+length;
1438 int ch;
1439
1440 if ('[' == UTF8_PEEK (ptr, limit))
1441 {
1442 if (! _Jv_VerifyOne (++ptr, limit, false))
1443 throw_class_format_error ("erroneous class name");
1444 else
1445 return;
1446 }
1447
1448 next_level:
1449 do {
1450 if ((ch = UTF8_GET (ptr, limit))==-1)
1451 throw_class_format_error ("erroneous class name");
1452 if (! is_identifier_start (ch))
1453 throw_class_format_error ("erroneous class name");
1454 do {
1455 if (ptr == limit)
1456 return;
1457 else if ((ch = UTF8_GET (ptr, limit))==-1)
1458 throw_class_format_error ("erroneous class name");
1459 else if (ch == '.')
1460 goto next_level;
1461 else if (! is_identifier_part (ch))
1462 throw_class_format_error ("erroneous class name");
1463 } while (true);
1464 } while (true);
1465
1466 }
1467
1468 void
1469 _Jv_VerifyClassName (_Jv_Utf8Const *name)
1470 {
1471 _Jv_VerifyClassName ((unsigned char*)&name->data[0],
1472 (_Jv_ushort) name->length);
1473 }
1474
1475
1476 /** returns true, if name1 and name2 represents classes in the same
1477 package. */
1478
1479 bool
1480 _Jv_ClassNameSamePackage (_Jv_Utf8Const *name1, _Jv_Utf8Const *name2)
1481 {
1482 unsigned char* ptr1 = (unsigned char*) name1->data;
1483 unsigned char* limit1 = ptr1 + name1->length;
1484
1485 unsigned char* last1 = ptr1;
1486
1487 // scan name1, and find the last occurrence of '.'
1488 while (ptr1 < limit1) {
1489 int ch1 = UTF8_GET (ptr1, limit1);
1490
1491 if (ch1 == '.')
1492 last1 = ptr1;
1493
1494 else if (ch1 == -1)
1495 return false;
1496 }
1497
1498 // now the length of name1's package name is len
1499 int len = last1 - (unsigned char*) name1->data;
1500
1501 // if this is longer than name2, then we're off
1502 if (len > name2->length)
1503 return false;
1504
1505 // then compare the first len bytes for equality
1506 if (memcmp ((void*) name1->data, (void*) name2->data, len) == 0)
1507 {
1508 // check that there are no .'s after position len in name2
1509
1510 unsigned char* ptr2 = (unsigned char*) name2->data + len;
1511 unsigned char* limit2 =
1512 (unsigned char*) name2->data + name2->length;
1513
1514 while (ptr2 < limit2)
1515 {
1516 int ch2 = UTF8_GET (ptr2, limit2);
1517 if (ch2 == -1 || ch2 == '.')
1518 return false;
1519 }
1520 return true;
1521 }
1522 return false;
1523 }
1524
1525
1526 \f
1527 /** Here we define the exceptions that can be thrown */
1528
1529 static void
1530 throw_no_class_def_found_error (jstring msg)
1531 {
1532 if (msg == 0)
1533 JvThrow (new java::lang::NoClassDefFoundError);
1534 else
1535 JvThrow (new java::lang::NoClassDefFoundError (msg));
1536 }
1537
1538 static void
1539 throw_no_class_def_found_error (char *msg)
1540 {
1541 throw_no_class_def_found_error (JvNewStringLatin1 (msg));
1542 }
1543
1544 static void
1545 throw_class_format_error (jstring msg)
1546 {
1547 if (msg == 0)
1548 JvThrow (new java::lang::ClassFormatError);
1549 else
1550 JvThrow (new java::lang::ClassFormatError (msg));
1551 }
1552
1553 static void
1554 throw_class_format_error (char *msg)
1555 {
1556 throw_class_format_error (JvNewStringLatin1 (msg));
1557 }
1558
1559 static void
1560 throw_internal_error (char *msg)
1561 {
1562 JvThrow
1563 (new java::lang::InternalError (JvNewStringLatin1 (msg)));
1564 }
1565
1566 static jfloat int_bits_to_float (jint value)
1567 {
1568 return java::lang::Float::intBitsToFloat (value);
1569 }
1570
1571 static jdouble long_bits_to_double (jlong value)
1572 {
1573 return java::lang::Double::longBitsToDouble (value);
1574 }
1575
1576 static void throw_incompatible_class_change_error (jstring msg)
1577 {
1578 JvThrow (new java::lang::IncompatibleClassChangeError (msg));
1579 }
1580
1581 static void throw_class_circularity_error (jstring msg)
1582 {
1583 JvThrow (new java::lang::ClassCircularityError (msg));
1584 }
1585
1586 #endif /* INTERPRETER */
1587
This page took 0.105576 seconds and 5 git commands to generate.