1 // resolve.cc - Code for linking and resolving classes and pool entries.
3 /* Copyright (C) 1999 Cygnus Solutions
5 This file is part of libgcj.
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
11 /* Author: Kresten Krab Thorup <krab@gnu.org> */
15 #include <java-interp.h>
20 #include <java-cpool.h>
21 #include <java/lang/Class.h>
22 #include <java/lang/String.h>
23 #include <java/lang/Thread.h>
24 #include <java/lang/InternalError.h>
25 #include <java/lang/VirtualMachineError.h>
26 #include <java/lang/NoSuchFieldError.h>
27 #include <java/lang/ClassFormatError.h>
28 #include <java/lang/IllegalAccessError.h>
29 #include <java/lang/AbstractMethodError.h>
30 #include <java/lang/ClassNotFoundException.h>
31 #include <java/lang/IncompatibleClassChangeError.h>
32 #include <java/lang/reflect/Modifier.h>
36 static void throw_internal_error (char *msg
)
37 __attribute__ ((__noreturn__
));
38 static void throw_class_format_error (jstring msg
)
39 __attribute__ ((__noreturn__
));
40 static void throw_class_format_error (char *msg
)
41 __attribute__ ((__noreturn__
));
43 #define StringClass _CL_Q34java4lang6String
44 extern java::lang::Class StringClass
;
45 #define ClassObject _CL_Q34java4lang6Object
46 extern java::lang::Class ClassObject
;
47 #define ObjectClass _CL_Q34java4lang6Object
48 extern java::lang::Class ObjectClass
;
51 static int get_alignment_from_class (jclass
);
53 static _Jv_ResolvedMethod
*
54 _Jv_BuildResolvedMethod (_Jv_Method
*,
60 // We need to know the name of a constructor.
61 static _Jv_Utf8Const
*init_name
= _Jv_makeUtf8Const ("<init>", 6);
63 static void throw_incompatible_class_change_error (jstring msg
)
65 JvThrow (new java::lang::IncompatibleClassChangeError (msg
));
69 _Jv_ResolvePoolEntry (jclass klass
, int index
)
71 using namespace java::lang::reflect
;
73 _Jv_Constants
*pool
= &klass
->constants
;
75 if ((pool
->tags
[index
] & JV_CONSTANT_ResolvedFlag
) != 0)
76 return pool
->data
[index
];
78 switch (pool
->tags
[index
]) {
79 case JV_CONSTANT_Class
:
81 _Jv_Utf8Const
*name
= pool
->data
[index
].utf8
;
84 if (name
->data
[0] == '[')
85 found
= _Jv_FindClassFromSignature (&name
->data
[0],
88 found
= _Jv_FindClass (name
, klass
->loader
);
92 jstring str
= _Jv_NewStringUTF (name
->data
);
93 JvThrow (new java::lang::ClassNotFoundException (str
));
96 if ((found
->accflags
& Modifier::PUBLIC
) == Modifier::PUBLIC
97 || (_Jv_ClassNameSamePackage (found
->name
,
100 pool
->data
[index
].clazz
= found
;
101 pool
->tags
[index
] |= JV_CONSTANT_ResolvedFlag
;
105 JvThrow (new java::lang::IllegalAccessError (found
->getName()));
110 case JV_CONSTANT_String
:
113 str
= _Jv_NewStringUtf8Const (pool
->data
[index
].utf8
);
114 pool
->data
[index
].o
= str
;
115 pool
->tags
[index
] |= JV_CONSTANT_ResolvedFlag
;
120 case JV_CONSTANT_Fieldref
:
122 _Jv_ushort class_index
, name_and_type_index
;
123 _Jv_loadIndexes (&pool
->data
[index
],
125 name_and_type_index
);
126 jclass owner
= (_Jv_ResolvePoolEntry (klass
, class_index
)).clazz
;
129 _Jv_InitClass (owner
);
131 _Jv_ushort name_index
, type_index
;
132 _Jv_loadIndexes (&pool
->data
[name_and_type_index
],
136 _Jv_Utf8Const
*field_name
= pool
->data
[name_index
].utf8
;
137 _Jv_Utf8Const
*field_type_name
= pool
->data
[type_index
].utf8
;
139 // FIXME: The implementation of this function
140 // (_Jv_FindClassFromSignature) will generate an instance of
141 // _Jv_Utf8Const for each call if the field type is a class name
142 // (Lxx.yy.Z;). This may be too expensive to do for each and
143 // every fieldref being resolved. For now, we fix the problem by
144 // only doing it when we have a loader different from the class
145 // declaring the field.
147 jclass field_type
= 0;
149 if (owner
->loader
!= klass
->loader
)
150 field_type
= _Jv_FindClassFromSignature (field_type_name
->data
,
153 _Jv_Field
* the_field
= 0;
155 for (jclass cls
= owner
; cls
!= 0; cls
= cls
->getSuperclass ())
157 for (int i
= 0; i
< cls
->field_count
; i
++)
159 _Jv_Field
*field
= &cls
->fields
[i
];
160 if (! _Jv_equalUtf8Consts (field
->name
, field_name
))
163 // now, check field access.
166 || ((field
->flags
& Modifier::PUBLIC
) != 0)
167 || (((field
->flags
& Modifier::PROTECTED
) != 0)
168 && cls
->isAssignableFrom (klass
))
169 || (((field
->flags
& Modifier::PRIVATE
) == 0)
170 && _Jv_ClassNameSamePackage (cls
->name
,
173 /* resove the field using the class' own loader
176 if (!field
->isResolved ())
177 _Jv_ResolveField (field
, cls
->loader
);
179 if (field_type
!= 0 && field
->type
!= field_type
)
181 (new java::lang::LinkageError
183 ("field type mismatch with different loaders")));
186 goto end_of_field_search
;
190 JvThrow (new java::lang::IllegalAccessError
);
198 jstring msg
= JvNewStringLatin1 ("field ");
199 msg
= msg
->concat (owner
->getName ());
200 msg
= msg
->concat (JvNewStringLatin1("."));
201 msg
= msg
->concat (_Jv_NewStringUTF (field_name
->data
));
202 msg
= msg
->concat (JvNewStringLatin1(" was not found."));
203 throw_incompatible_class_change_error (msg
);
206 pool
->data
[index
].field
= the_field
;
207 pool
->tags
[index
] |= JV_CONSTANT_ResolvedFlag
;
211 case JV_CONSTANT_Methodref
:
212 case JV_CONSTANT_InterfaceMethodref
:
214 _Jv_ushort class_index
, name_and_type_index
;
215 _Jv_loadIndexes (&pool
->data
[index
],
217 name_and_type_index
);
218 jclass owner
= (_Jv_ResolvePoolEntry (klass
, class_index
)).clazz
;
221 _Jv_InitClass (owner
);
223 _Jv_ushort name_index
, type_index
;
224 _Jv_loadIndexes (&pool
->data
[name_and_type_index
],
228 _Jv_Utf8Const
*method_name
= pool
->data
[name_index
].utf8
;
229 _Jv_Utf8Const
*method_signature
= pool
->data
[type_index
].utf8
;
231 int vtable_index
= -1;
232 _Jv_Method
*the_method
= 0;
233 jclass found_class
= 0;
235 // we make a loop here, because methods are allowed to be moved to
236 // a super class, and still be visible.. (binary compatibility).
238 for (jclass cls
= owner
; cls
!= 0; cls
= cls
->getSuperclass ())
240 for (int i
= 0; i
< cls
->method_count
; i
++)
242 _Jv_Method
*method
= &cls
->methods
[i
];
243 if ( (!_Jv_equalUtf8Consts (method
->name
,
245 || (!_Jv_equalUtf8Consts (method
->signature
,
250 || ((method
->accflags
& Modifier::PUBLIC
) != 0)
251 || (((method
->accflags
& Modifier::PROTECTED
) != 0)
252 && cls
->isAssignableFrom (klass
))
253 || (((method
->accflags
& Modifier::PRIVATE
) == 0)
254 && _Jv_ClassNameSamePackage (cls
->name
,
257 // FIXME: if (cls->loader != klass->loader), then we
258 // must actually check that the types of arguments
259 // correspond. That is, for each argument type, and
260 // the return type, doing _Jv_FindClassFromSignature
261 // with either loader should produce the same result,
262 // i.e., exactly the same jclass object. JVMS 5.4.3.3
268 if (pool
->tags
[index
] == JV_CONSTANT_InterfaceMethodref
)
271 vtable_index
= _Jv_DetermineVTableIndex
272 (cls
, method_name
, method_signature
);
274 if (vtable_index
== 0)
275 throw_incompatible_class_change_error
276 (JvNewStringLatin1 ("method not found"));
278 goto end_of_method_search
;
282 JvThrow (new java::lang::IllegalAccessError
);
287 end_of_method_search
:
290 jstring msg
= JvNewStringLatin1 ("method ");
291 msg
= msg
->concat (owner
->getName ());
292 msg
= msg
->concat (JvNewStringLatin1("."));
293 msg
= msg
->concat (_Jv_NewStringUTF (method_name
->data
));
294 msg
= msg
->concat (JvNewStringLatin1(" was not found."));
295 JvThrow(new java::lang::NoSuchFieldError (msg
));
298 pool
->data
[index
].rmethod
=
299 _Jv_BuildResolvedMethod(the_method
,
301 (the_method
->accflags
& Modifier::STATIC
) != 0,
303 pool
->tags
[index
] |= JV_CONSTANT_ResolvedFlag
;
309 return pool
->data
[index
];
314 _Jv_ResolveField (_Jv_Field
*field
, java::lang::ClassLoader
*loader
)
316 if (! field
->isResolved ())
318 _Jv_Utf8Const
*sig
= (_Jv_Utf8Const
*)field
->type
;
319 field
->type
= _Jv_FindClassFromSignature (sig
->data
, loader
);
320 field
->flags
&= ~_Jv_FIELD_UNRESOLVED_FLAG
;
325 _Jv_LookupDeclaredMethod (jclass klass
, _Jv_Utf8Const
*name
,
326 _Jv_Utf8Const
*signature
)
328 for (; klass
; klass
= klass
->getSuperclass())
330 _Jv_Method
*meth
= _Jv_GetMethodLocal (klass
, name
, signature
);
339 /** FIXME: this is a terribly inefficient algorithm! It would improve
340 things if compiled classes to know vtable offset, and _Jv_Method had
343 Returns 0 if this class does not declare the given method.
344 Returns -1 if the given method does not appear in the vtable.
345 i.e., it is static, private, final or a constructor.
346 Otherwise, returns the vtable index. */
348 _Jv_DetermineVTableIndex (jclass klass
,
350 _Jv_Utf8Const
*signature
)
352 using namespace java::lang::reflect
;
354 jclass super_class
= klass
->getSuperclass ();
356 if (super_class
!= NULL
)
358 int prev
= _Jv_DetermineVTableIndex (super_class
,
365 /* at this point, we know that the super-class does not declare
366 * the method. Otherwise, the above call would have found it, and
367 * determined the result of this function (-1 or some positive
371 _Jv_Method
*meth
= _Jv_GetMethodLocal (klass
, name
, signature
);
373 /* now, if we do not declare this method, return zero */
377 /* so now, we know not only that the super class does not declare the
378 * method, but we do! So, this is a first declaration of the method. */
380 /* now, the checks for things that are declared in this class, but do
381 * not go into the vtable. There are three cases.
382 * 1) the method is static, private or final
383 * 2) the class itself is final, or
384 * 3) it is the method <init>
387 if ((meth
->accflags
& (Modifier::STATIC
389 | Modifier::FINAL
)) != 0
390 || (klass
->accflags
& Modifier::FINAL
) != 0
391 || _Jv_equalUtf8Consts (name
, init_name
))
394 /* reaching this point, we know for sure, that the method in question
395 * will be in the vtable. The question is where. */
397 /* the base offset, is where we will start assigning vtable
398 * indexes for this class. It is 1 for base classes
399 * (vtable->method[0] is unused), and for non-base classes it is the
400 * number of entries in the super class' vtable plus 1. */
403 if (super_class
== 0)
406 base_offset
= super_class
->vtable_method_count
+1;
408 /* we will consider methods 0..this_method_index-1. And for each one,
409 * determine if it is new (i.e., if it appears in the super class),
410 * and if it should go in the vtable. If so, increment base_offset */
412 int this_method_index
= meth
- (&klass
->methods
[0]);
414 for (int i
= 0; i
< this_method_index
; i
++)
416 _Jv_Method
*m
= &klass
->methods
[i
];
418 /* fist some checks for things that surely do not go in the
421 if ((m
->accflags
& (Modifier::STATIC
| Modifier::PRIVATE
)) != 0)
423 if (_Jv_equalUtf8Consts (m
->name
, init_name
))
426 /* Then, we need to know if this method appears in the
427 superclass. (This is where this function gets expensive) */
428 _Jv_Method
*sm
= _Jv_LookupDeclaredMethod (super_class
,
432 /* if it was somehow declared in the superclass, skip this */
436 /* but if it is final, and not declared in the super class,
437 * then we also skip it */
438 if ((m
->accflags
& Modifier::FINAL
) != 0)
441 /* finally, we can assign the index of this method */
442 /* m->vtable_index = base_offset */
449 /* this is installed in place of abstract methods */
451 _Jv_abstractMethodError ()
453 JvThrow (new java::lang::AbstractMethodError
);
457 _Jv_PrepareClass(jclass klass
)
459 using namespace java::lang::reflect
;
462 * The job of this function is to: 1) assign storage to fields, and 2)
463 * build the vtable. static fields are assigned real memory, instance
464 * fields are assigned offsets.
466 * NOTE: we have a contract with the garbage collector here. Static
467 * reference fields must not be resolved, until after they have storage
468 * assigned which is the check used by the collector to see if it
469 * should indirect the static field reference and mark the object
472 * Most fields are resolved lazily (i.e. have their class-type
473 * assigned) when they are accessed the first time by calling as part
474 * of _Jv_ResolveField, which is allways called after _Jv_PrepareClass.
475 * Static fields with initializers are resolved as part of this
476 * function, as are fields with primitive types.
479 if (! _Jv_IsInterpretedClass (klass
))
482 if (klass
->state
>= JV_STATE_PREPARED
)
485 // make sure super-class is linked. This involves taking a lock on
486 // the super class, so we use the Java method resolveClass, which will
487 // unlock it properly, should an exception happen.
489 java::lang::ClassLoader::resolveClass0 (klass
->superclass
);
491 _Jv_InterpClass
*clz
= (_Jv_InterpClass
*)klass
;
493 /************ PART ONE: OBJECT LAYOUT ***************/
498 // java.lang.Object is never interpreted!
499 instance_size
= clz
->superclass
->size ();
502 for (int i
= 0; i
< clz
->field_count
; i
++)
507 _Jv_Field
*field
= &clz
->fields
[i
];
509 if (! field
->isRef ())
511 // it's safe to resolve the field here, since it's
512 // a primitive class, which does not cause loading to happen.
513 _Jv_ResolveField (field
, clz
->loader
);
515 field_size
= field
->type
->size ();
516 field_align
= get_alignment_from_class (field
->type
);
520 field_size
= sizeof (jobject
);
521 field_align
= __alignof__ (jobject
);
524 #ifndef COMPACT_FIELDS
525 field
->bsize
= field_size
;
528 if (field
->flags
& Modifier::STATIC
)
530 /* this computes an offset into a region we'll allocate
531 shortly, and then add this offset to the start address */
533 static_size
= ROUND (static_size
, field_align
);
534 field
->u
.boffset
= static_size
;
535 static_size
+= field_size
;
539 instance_size
= ROUND (instance_size
, field_align
);
540 field
->u
.boffset
= instance_size
;
541 instance_size
+= field_size
;
545 // set the instance size for the class
546 clz
->size_in_bytes
= instance_size
;
548 // allocate static memory
549 if (static_size
!= 0)
551 char *static_data
= (char*)_Jv_AllocBytesChecked (static_size
);
553 memset (static_data
, 0, static_size
);
555 for (int i
= 0; i
< clz
->field_count
; i
++)
557 _Jv_Field
*field
= &clz
->fields
[i
];
559 if ((field
->flags
& Modifier::STATIC
) != 0)
561 field
->u
.addr
= static_data
+ field
->u
.boffset
;
563 if (clz
->field_initializers
[i
] != 0)
565 _Jv_ResolveField (field
, clz
->loader
);
566 _Jv_InitField (0, clz
, i
);
571 // now we don't need the field_initializers anymore, so let the
572 // collector get rid of it!
574 clz
->field_initializers
= 0;
577 /************ PART TWO: VTABLE LAYOUT ***************/
579 /* preparation: build the vtable stubs (even interfaces can)
580 have code -- for static constructors. */
581 for (int i
= 0; i
< clz
->method_count
; i
++)
583 _Jv_InterpMethod
*imeth
= clz
->interpreted_methods
[i
];
585 if (imeth
!= 0) // it could be abstract or native
587 clz
->methods
[i
].ncode
= imeth
->ncode ();
591 if ((clz
->methods
[i
].accflags
& Modifier::NATIVE
) != 0)
594 (new java::lang::VirtualMachineError
596 ("the interpreter does not support native methods")));
601 if (clz
->accflags
& Modifier::INTERFACE
)
603 clz
->state
= JV_STATE_PREPARED
;
608 /* FIXME: native methods for interpreted classes should be handled, I
609 * dunno exactly how, but it seems that we should try to find them at
610 * this point, and if we fail, try again after <clinit>, since it
611 * could have caused additional code to be loaded. Interfaces cannot
612 * have native methods (not even for static initialization). */
615 /* Now onto the actual job: vtable layout. First, count how many new
617 int new_method_count
= 0;
619 jclass super_class
= clz
->getSuperclass ();
621 if (super_class
== 0)
622 throw_internal_error ("cannot handle interpreted base classes");
624 for (int i
= 0; i
< clz
->method_count
; i
++)
626 _Jv_Method
*this_meth
= &clz
->methods
[i
];
628 if ((this_meth
->accflags
& (Modifier::STATIC
| Modifier::PRIVATE
)) != 0
629 || _Jv_equalUtf8Consts (this_meth
->name
, init_name
))
631 /* skip this, it doesn't go in the vtable */
635 _Jv_Method
*orig_meth
= _Jv_LookupDeclaredMethod (super_class
,
637 this_meth
->signature
);
641 // new methods that are final, also don't go in the vtable
642 if ((this_meth
->accflags
& Modifier::FINAL
) != 0)
645 new_method_count
+= 1;
649 if ((orig_meth
->accflags
& (Modifier::STATIC
651 | Modifier::FINAL
)) != 0
652 || ((orig_meth
->accflags
& Modifier::ABSTRACT
) == 0
653 && (this_meth
->accflags
& Modifier::ABSTRACT
) != 0
654 && (klass
->accflags
& Modifier::ABSTRACT
) == 0))
656 clz
->state
= JV_STATE_ERROR
;
658 JvThrow (new java::lang::IncompatibleClassChangeError
662 /* FIXME: At this point, if (loader != super_class->loader), we
663 * need to "impose class loader constraints" for the types
664 * involved in the signature of this method */
668 int vtable_count
= (super_class
->vtable_method_count
) + new_method_count
;
669 clz
->vtable_method_count
= vtable_count
;
671 /* allocate vtable structure */
672 _Jv_VTable
*vtable
= (_Jv_VTable
*)
673 _Jv_AllocBytesChecked (sizeof (_Jv_VTable
)
674 + (sizeof (void*) * (vtable_count
)));
677 /* copy super class' vtable entries (index 0 goes unused). */
678 memcpy ((void*)&vtable
->method
[1],
679 (void*)&super_class
->vtable
->method
[1],
680 sizeof (void*) * super_class
->vtable_method_count
);
682 /* now, install our own vtable entries, reprise... */
683 for (int i
= 0; i
< clz
->method_count
; i
++)
685 _Jv_Method
*this_meth
= &clz
->methods
[i
];
687 int index
= _Jv_DetermineVTableIndex (clz
,
689 this_meth
->signature
);
692 throw_internal_error ("method now found in own class");
696 if (index
> clz
->vtable_method_count
+1)
697 throw_internal_error ("vtable problem...");
699 if (clz
->interpreted_methods
[i
] == 0)
700 vtable
->method
[index
] = (void*)&_Jv_abstractMethodError
;
702 vtable
->method
[index
] = this_meth
->ncode
;
706 /* finally, assign the vtable! */
707 clz
->vtable
= vtable
;
709 /* wooha! we're done. */
710 clz
->state
= JV_STATE_PREPARED
;
714 /** Do static initialization for fields with a constant initializer */
716 _Jv_InitField (jobject obj
, jclass klass
, int index
)
718 using namespace java::lang::reflect
;
720 if (obj
!= 0 && klass
== 0)
721 klass
= obj
->getClass ();
723 if (!_Jv_IsInterpretedClass (klass
))
726 _Jv_InterpClass
*clz
= (_Jv_InterpClass
*)klass
;
728 _Jv_Field
* field
= (&clz
->fields
[0]) + index
;
730 if (index
> clz
->field_count
)
731 throw_internal_error ("field out of range");
733 int init
= clz
->field_initializers
[index
];
737 _Jv_Constants
*pool
= &clz
->constants
;
738 int tag
= pool
->tags
[init
];
740 if (! field
->isResolved ())
741 throw_internal_error ("initializing unresolved field");
743 if (obj
==0 && ((field
->flags
& Modifier::STATIC
) == 0))
744 throw_internal_error ("initializing non-static field with no object");
748 if ((field
->flags
& Modifier::STATIC
) != 0)
749 addr
= (void*) field
->u
.addr
;
751 addr
= (void*) (((char*)obj
) + field
->u
.boffset
);
755 case JV_CONSTANT_String
:
757 _Jv_MonitorEnter (clz
);
759 str
= _Jv_NewStringUtf8Const (pool
->data
[init
].utf8
);
760 pool
->data
[init
].string
= str
;
761 pool
->tags
[init
] = JV_CONSTANT_ResolvedString
;
762 _Jv_MonitorExit (clz
);
766 case JV_CONSTANT_ResolvedString
:
767 if (! (field
->type
== &StringClass
|| field
->type
== &ObjectClass
))
768 throw_class_format_error ("string initialiser to non-string field");
770 *(jstring
*)addr
= pool
->data
[init
].string
;
773 case JV_CONSTANT_Integer
:
775 int value
= pool
->data
[init
].i
;
777 if (field
->type
== JvPrimClass (boolean
))
778 *(jboolean
*)addr
= (jboolean
)value
;
780 else if (field
->type
== JvPrimClass (byte
))
781 *(jbyte
*)addr
= (jbyte
)value
;
783 else if (field
->type
== JvPrimClass (char))
784 *(jchar
*)addr
= (jchar
)value
;
786 else if (field
->type
== JvPrimClass (short))
787 *(jshort
*)addr
= (jshort
)value
;
789 else if (field
->type
== JvPrimClass (int))
790 *(jint
*)addr
= (jint
)value
;
793 throw_class_format_error ("erroneous field initializer");
797 case JV_CONSTANT_Long
:
798 if (field
->type
!= JvPrimClass (long))
799 throw_class_format_error ("erroneous field initializer");
801 *(jlong
*)addr
= _Jv_loadLong (&pool
->data
[init
]);
804 case JV_CONSTANT_Float
:
805 if (field
->type
!= JvPrimClass (float))
806 throw_class_format_error ("erroneous field initializer");
808 *(jfloat
*)addr
= pool
->data
[init
].f
;
811 case JV_CONSTANT_Double
:
812 if (field
->type
!= JvPrimClass (double))
813 throw_class_format_error ("erroneous field initializer");
815 *(jdouble
*)addr
= _Jv_loadDouble (&pool
->data
[init
]);
819 throw_class_format_error ("erroneous field initializer");
824 get_alignment_from_class (jclass klass
)
826 if (klass
== JvPrimClass (byte
))
827 return __alignof__ (jbyte
);
828 else if (klass
== JvPrimClass (short))
829 return __alignof__ (jshort
);
830 else if (klass
== JvPrimClass (int))
831 return __alignof__ (jint
);
832 else if (klass
== JvPrimClass (long))
833 return __alignof__ (jlong
);
834 else if (klass
== JvPrimClass (boolean
))
835 return __alignof__ (jboolean
);
836 else if (klass
== JvPrimClass (char))
837 return __alignof__ (jchar
);
838 else if (klass
== JvPrimClass (float))
839 return __alignof__ (jfloat
);
840 else if (klass
== JvPrimClass (double))
841 return __alignof__ (jdouble
);
843 return __alignof__ (jobject
);
847 inline static unsigned char*
848 skip_one_type (unsigned char* ptr
)
859 do { ch
= *ptr
++; } while (ch
!= ';');
866 get_ffi_type_from_signature (unsigned char* ptr
)
872 return &ffi_type_pointer
;
877 return &ffi_type_sint8
;
881 return &ffi_type_uint16
;
885 return &ffi_type_sint16
;
889 return &ffi_type_sint32
;
893 return &ffi_type_sint64
;
897 return &ffi_type_float
;
901 return &ffi_type_double
;
905 return &ffi_type_void
;
909 throw_internal_error ("unknown type in signature");
912 /* this function yields the number of actual arguments, that is, if the
913 * function is non-static, then one is added to the number of elements
914 * found in the signature */
917 count_arguments (_Jv_Utf8Const
*signature
,
920 unsigned char *ptr
= (unsigned char*) signature
->data
;
921 int arg_count
= staticp
? 0 : 1;
923 /* first, count number of arguments */
931 ptr
= skip_one_type (ptr
);
938 /* This beast will build a cif, given the signature. Memory for
939 * the cif itself and for the argument types must be allocated by the
944 init_cif (_Jv_Utf8Const
* signature
,
948 ffi_type
**arg_types
)
950 unsigned char *ptr
= (unsigned char*) signature
->data
;
952 int arg_index
= 0; // arg number
953 int item_count
= 0; // stack-item count
958 arg_types
[arg_index
++] = &ffi_type_pointer
;
968 arg_types
[arg_index
++] = get_ffi_type_from_signature (ptr
);
970 if (*ptr
== 'J' || *ptr
== 'D')
975 ptr
= skip_one_type (ptr
);
980 ffi_type
*rtype
= get_ffi_type_from_signature (ptr
);
982 ptr
= skip_one_type (ptr
);
983 if (ptr
!= (unsigned char*)signature
->data
+ signature
->length
)
984 throw_internal_error ("did not find end of signature");
986 if (ffi_prep_cif (cif
, FFI_DEFAULT_ABI
,
987 arg_count
, rtype
, arg_types
) != FFI_OK
)
988 throw_internal_error ("ffi_prep_cif failed");
994 /* we put this one here, and not in interpret.cc because it
995 * calls the utility routines count_arguments
996 * which are static to this module. The following struct defines the
997 * layout we use for the stubs, it's only used in the ncode method. */
1000 ffi_raw_closure closure
;
1002 ffi_type
*arg_types
[0];
1005 typedef void (*ffi_closure_fun
) (ffi_cif
*,void*,ffi_raw
*,void*);
1008 _Jv_InterpMethod::ncode ()
1010 using namespace java::lang::reflect
;
1012 if (self
->ncode
!= 0)
1015 jboolean staticp
= (self
->accflags
& Modifier::STATIC
) != 0;
1016 int arg_count
= count_arguments (self
->signature
, staticp
);
1018 ncode_closure
*closure
=
1019 (ncode_closure
*)_Jv_AllocBytesChecked (sizeof (ncode_closure
)
1020 + arg_count
* sizeof (ffi_type
*));
1022 init_cif (self
->signature
,
1026 &closure
->arg_types
[0]);
1028 ffi_closure_fun fun
;
1030 args_raw_size
= ffi_raw_size (&closure
->cif
);
1032 if ((self
->accflags
& Modifier::SYNCHRONIZED
) != 0)
1035 fun
= (ffi_closure_fun
)&_Jv_InterpMethod::run_synch_class
;
1037 fun
= (ffi_closure_fun
)&_Jv_InterpMethod::run_synch_object
;
1041 fun
= (ffi_closure_fun
)&_Jv_InterpMethod::run_normal
;
1044 ffi_prep_raw_closure (&closure
->closure
,
1049 self
->ncode
= (void*)closure
;
1054 /* A _Jv_ResolvedMethod is what is put in the constant pool for a
1055 * MethodRef or InterfacemethodRef. */
1056 static _Jv_ResolvedMethod
*
1057 _Jv_BuildResolvedMethod (_Jv_Method
* method
,
1062 int arg_count
= count_arguments (method
->signature
, staticp
);
1064 _Jv_ResolvedMethod
* result
= (_Jv_ResolvedMethod
*)
1065 _Jv_AllocBytesChecked (sizeof (_Jv_ResolvedMethod
)
1066 + arg_count
*sizeof (ffi_type
*));
1068 result
->stack_item_count
1069 = init_cif (method
->signature
,
1073 &result
->arg_types
[0]);
1075 result
->vtable_index
= vtable_index
;
1076 result
->method
= method
;
1077 result
->klass
= klass
;
1084 throw_class_format_error (jstring msg
)
1087 JvThrow (new java::lang::ClassFormatError
);
1089 JvThrow (new java::lang::ClassFormatError (msg
));
1093 throw_class_format_error (char *msg
)
1095 throw_class_format_error (JvNewStringLatin1 (msg
));
1099 throw_internal_error (char *msg
)
1102 (new java::lang::InternalError (JvNewStringLatin1 (msg
)));
1106 #endif /* INTERPRETER */