* classcache_lookup_name, classcache_new_name: Speed up lookup in external
[cacao.git] / src / vm / builtin.c
1 /* src/vm/builtin.c - functions for unsupported operations
2
3    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Reinhard Grafl
28             Andreas Krall
29             Mark Probst
30
31    Changes: Christian Thalinger
32
33    Contains C functions for JavaVM Instructions that cannot be
34    translated to machine language directly. Consequently, the
35    generated machine code for these instructions contains function
36    calls instead of machine instructions, using the C calling
37    convention.
38
39    $Id: builtin.c 3239 2005-09-21 14:09:22Z twisti $
40
41 */
42
43
44 #include <assert.h>
45 #include <stdlib.h>
46 #include <string.h>
47
48 #include "config.h"
49 #include "vm/types.h"
50
51 #include "arch.h"
52 #include "md-abi.h"
53
54 #include "classpath/native/fdlibm/fdlibm.h"
55
56 #include "mm/boehm.h"
57 #include "mm/memory.h"
58 #include "native/native.h"
59 #include "native/include/java_lang_Cloneable.h"
60 #include "native/include/java_lang_Object.h"          /* required by VMObject */
61 #include "native/include/java_lang_VMObject.h"
62
63 #if defined(USE_THREADS)
64 # if defined(NATIVE_THREADS)
65 #  include "threads/native/threads.h"
66 # else
67 #  include "threads/green/threads.h"
68 #  include "threads/green/locks.h"
69 # endif
70 #endif
71
72 #include "toolbox/logging.h"
73 #include "toolbox/util.h"
74 #include "vm/builtin.h"
75 #include "vm/exceptions.h"
76 #include "vm/global.h"
77 #include "vm/initialize.h"
78 #include "vm/loader.h"
79 #include "vm/options.h"
80 #include "vm/stringlocal.h"
81 #include "vm/tables.h"
82 #include "vm/jit/asmpart.h"
83 #include "vm/jit/patcher.h"
84
85
86 /* include builtin tables *****************************************************/
87
88 #include "vm/builtintable.inc"
89
90
91 /* builtintable_init ***********************************************************
92
93    Parse the descriptors of builtin functions and create the parsed
94    descriptors.
95
96 *******************************************************************************/
97
98 static bool builtintable_init(void)
99 {
100         descriptor_pool *descpool;
101         s4               dumpsize;
102         utf             *descriptor;
103         s4               entries_internal;
104         s4               entries_automatic;
105         s4               i;
106
107         /* mark start of dump memory area */
108
109         dumpsize = dump_size();
110
111         /* create a new descriptor pool */
112
113         descpool = descriptor_pool_new(class_java_lang_Object);
114
115         /* add some entries we need */
116
117         if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
118                 return false;
119
120         if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
121                 return false;
122
123         /* calculate table entries statically */
124
125         entries_internal =
126                 sizeof(builtintable_internal) / sizeof(builtintable_entry);
127
128         entries_automatic =
129                 sizeof(builtintable_automatic) / sizeof(builtintable_entry)
130                 - 1; /* last filler entry (comment see builtintable.inc) */
131
132         /* first add all descriptors to the pool */
133
134         for (i = 0; i < entries_internal; i++) {
135                 /* create a utf8 string from descriptor */
136
137                 descriptor = utf_new_char(builtintable_internal[i].descriptor);
138
139                 if (!descriptor_pool_add(descpool, descriptor, NULL)) {
140                         /* release dump area */
141
142                         dump_release(dumpsize);
143
144                         return false;
145                 }
146         }
147
148         for (i = 0; i < entries_automatic; i++) {
149                 /* create a utf8 string from descriptor */
150
151                 descriptor = utf_new_char(builtintable_automatic[i].descriptor);
152
153                 if (!descriptor_pool_add(descpool, descriptor, NULL)) {
154                         /* release dump area */
155
156                         dump_release(dumpsize);
157
158                         return false;
159                 }
160         }
161
162         /* create the class reference table */
163
164         (void) descriptor_pool_create_classrefs(descpool, NULL);
165
166         /* allocate space for the parsed descriptors */
167
168         descriptor_pool_alloc_parsed_descriptors(descpool);
169
170         /* now parse all descriptors */
171
172         for (i = 0; i < entries_internal; i++) {
173                 /* create a utf8 string from descriptor */
174
175                 descriptor = utf_new_char(builtintable_internal[i].descriptor);
176
177                 /* parse the descriptor, builtin is always static (no `this' pointer) */
178
179                 builtintable_internal[i].md =
180                         descriptor_pool_parse_method_descriptor(descpool, descriptor,
181                                                                                                         ACC_STATIC, NULL);
182         }
183
184         for (i = 0; i < entries_automatic; i++) {
185                 /* create a utf8 string from descriptor */
186
187                 descriptor = utf_new_char(builtintable_automatic[i].descriptor);
188
189                 /* parse the descriptor, builtin is always static (no `this' pointer) */
190
191                 builtintable_automatic[i].md =
192                         descriptor_pool_parse_method_descriptor(descpool, descriptor,
193                                                                                                         ACC_STATIC, NULL);
194         }
195
196         /* release dump area */
197
198         dump_release(dumpsize);
199
200         return true;
201 }
202
203
204 /* builtintable_comparator *****************************************************
205
206    qsort comparator for the automatic builtin table.
207
208 *******************************************************************************/
209
210 static int builtintable_comparator(const void *a, const void *b)
211 {
212         builtintable_entry *bte1;
213         builtintable_entry *bte2;
214
215         bte1 = (builtintable_entry *) a;
216         bte2 = (builtintable_entry *) b;
217
218         return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
219 }
220
221
222 /* builtintable_sort_automatic *************************************************
223
224    Sorts the automatic builtin table.
225
226 *******************************************************************************/
227
228 static void builtintable_sort_automatic(void)
229 {
230         s4 entries;
231
232         /* calculate table size statically (`- 1' comment see builtintable.inc) */
233
234         entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
235
236         qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
237                   builtintable_comparator);
238 }
239
240
241 /* builtin_init ****************************************************************
242
243    XXX
244
245 *******************************************************************************/
246
247 bool builtin_init(void)
248 {
249         /* initialize the builtin tables */
250
251         if (!builtintable_init())
252                 return false;
253
254         /* sort builtin tables */
255
256         builtintable_sort_automatic();
257
258         return true;
259 }
260
261
262 /* builtintable_get_internal ***************************************************
263
264    Finds an entry in the builtintable for internal functions and
265    returns the a pointer to the structure.
266
267 *******************************************************************************/
268
269 builtintable_entry *builtintable_get_internal(functionptr fp)
270 {
271         s4 i;
272
273         for (i = 0; builtintable_internal[i].fp != NULL; i++) {
274                 if (builtintable_internal[i].fp == fp)
275                         return &builtintable_internal[i];
276         }
277
278         return NULL;
279 }
280
281
282 /* builtintable_get_automatic **************************************************
283
284    Finds an entry in the builtintable for functions which are replaced
285    automatically and returns the a pointer to the structure.
286
287 *******************************************************************************/
288
289 builtintable_entry *builtintable_get_automatic(s4 opcode)
290 {
291         builtintable_entry *first;
292         builtintable_entry *last;
293         builtintable_entry *middle;
294         s4                  half;
295         s4                  entries;
296
297         /* calculate table size statically (`- 1' comment see builtintable.inc) */
298
299         entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
300
301         first = builtintable_automatic;
302         last = builtintable_automatic + entries;
303
304         while (entries > 0) {
305                 half = entries / 2;
306                 middle = first + half;
307
308                 if (middle->opcode < opcode) {
309                         first = middle + 1;
310                         entries -= half + 1;
311                 } else
312                         entries = half;
313         }
314
315         return (first != last ? first : NULL);
316 }
317
318
319 /*****************************************************************************
320                                                                 TYPE CHECKS
321 *****************************************************************************/
322
323
324
325 /*************** internal function: builtin_isanysubclass *********************
326
327         Checks a subclass relation between two classes. Implemented interfaces
328         are interpreted as super classes.
329         Return value:  1 ... sub is subclass of super
330                                    0 ... otherwise
331                                         
332 *****************************************************************************/                                  
333 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
334 {
335         s4 res;
336         castinfo classvalues;
337
338         if (sub == super)
339                 return 1;
340
341         if (super->flags & ACC_INTERFACE) {
342                 res = (sub->vftbl->interfacetablelength > super->index) &&
343                         (sub->vftbl->interfacetable[-super->index] != NULL);
344
345         } else {
346                 asm_getclassvalues_atomic(super->vftbl, sub->vftbl, &classvalues);
347
348                 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <=
349                         (u4) classvalues.super_diffval;
350         }
351
352         return res;
353 }
354
355
356 s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super)
357 {
358         s4 res;
359         s4 base;
360         castinfo classvalues;
361
362         if (sub == super)
363                 return 1;
364
365         asm_getclassvalues_atomic(super, sub, &classvalues);
366
367         if ((base = classvalues.super_baseval) <= 0) {
368                 /* super is an interface */
369                 res = (sub->interfacetablelength > -base) &&
370                         (sub->interfacetable[base] != NULL);
371         } else {
372             res = (u4) (classvalues.sub_baseval - classvalues.super_baseval)
373                         <= (u4) classvalues.super_diffval;
374         }
375
376         return res;
377 }
378
379
380 /****************** function: builtin_instanceof *****************************
381
382         Checks if an object is an instance of some given class (or subclass of
383         that class). If class is an interface, checks if the interface is
384         implemented.
385         Return value:  1 ... obj is an instance of class or implements the interface
386                                    0 ... otherwise or if obj == NULL
387                          
388 *****************************************************************************/
389
390 /* XXX should use vftbl */
391 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
392 {
393         if (!obj)
394                 return 0;
395
396         return builtin_isanysubclass(obj->vftbl->class, class);
397 }
398
399
400
401 /**************** function: builtin_checkcast *******************************
402
403         The same as builtin_instanceof except that 1 is returned when
404         obj == NULL
405                           
406 ****************************************************************************/
407
408 /* XXX should use vftbl */
409 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
410 {
411         if (obj == NULL)
412                 return 1;
413
414         if (builtin_isanysubclass(obj->vftbl->class, class))
415                 return 1;
416
417         return 0;
418 }
419
420
421 /* builtin_descriptorscompatible ***********************************************
422
423    Checks if two array type descriptors are assignment compatible
424
425    Return value: 1 ... target = desc is possible
426                  0 ... otherwise
427                         
428 *******************************************************************************/
429
430 static s4 builtin_descriptorscompatible(arraydescriptor *desc, arraydescriptor *target)
431 {
432         if (desc == target)
433                 return 1;
434
435         if (desc->arraytype != target->arraytype)
436                 return 0;
437
438         if (desc->arraytype != ARRAYTYPE_OBJECT)
439                 return 1;
440         
441         /* {both arrays are arrays of references} */
442
443         if (desc->dimension == target->dimension) {
444                 /* an array which contains elements of interface types is allowed to be casted to Object (JOWENN)*/
445                 if ( (desc->elementvftbl->baseval<0) && (target->elementvftbl->baseval==1) ) return 1;
446                 return builtin_isanysubclass_vftbl(desc->elementvftbl,target->elementvftbl);
447         }
448         if (desc->dimension < target->dimension) return 0;
449
450         /* {desc has higher dimension than target} */
451         return builtin_isanysubclass_vftbl(pseudo_class_Arraystub->vftbl, target->elementvftbl);
452 }
453
454
455 /* builtin_arraycheckcast ******************************************************
456
457    Checks if an object is really a subtype of the requested array
458    type.  The object has to be an array to begin with. For simple
459    arrays (int, short, double, etc.) the types have to match exactly.
460    For arrays of objects, the type of elements in the array has to be
461    a subtype (or the same type) of the requested element type. For
462    arrays of arrays (which in turn can again be arrays of arrays), the
463    types at the lowest level have to satisfy the corresponding sub
464    class relation.
465         
466 *******************************************************************************/
467
468 s4 builtin_arraycheckcast(java_objectheader *o, vftbl_t *target)
469 {
470         arraydescriptor *desc;
471
472         if (!o)
473                 return 1;
474
475         if ((desc = o->vftbl->arraydesc) == NULL)
476                 return 0;
477  
478         return builtin_descriptorscompatible(desc, target->arraydesc);
479 }
480
481
482 s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl_t *target)
483 {
484         if (!obj)
485                 return 1;
486
487         return builtin_arraycheckcast(obj, target);
488 }
489
490
491 /************************** exception functions *******************************
492
493 ******************************************************************************/
494
495 java_objectheader *builtin_throw_exception(java_objectheader *xptr)
496 {
497     java_lang_Throwable *t;
498         char                *logtext;
499         s4                   logtextlen;
500         s4                   dumpsize;
501
502         if (opt_verbose) {
503                 t = (java_lang_Throwable *) xptr;
504
505                 /* calculate message length */
506
507                 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
508
509                 if (t) {
510                         logtextlen +=
511                                 utf_strlen(xptr->vftbl->class->name) +
512                                 strlen(": ") +
513                                 javastring_strlen((java_objectheader *) t->detailMessage);
514
515                 } else
516                         logtextlen += strlen("(nil)");
517
518                 /* allocate memory */
519
520                 dumpsize = dump_size();
521
522                 logtext = DMNEW(char, logtextlen);
523
524                 strcpy(logtext, "Builtin exception thrown: ");
525
526                 if (t) {
527                         utf_sprint_classname(logtext + strlen(logtext),
528                                                                  xptr->vftbl->class->name);
529
530                         if (t->detailMessage) {
531                                 char *buf;
532
533                                 buf = javastring_tochar((java_objectheader *) t->detailMessage);
534                                 strcat(logtext, ": ");
535                                 strcat(logtext, buf);
536                                 MFREE(buf, char, strlen(buf));
537                         }
538
539                 } else {
540                         strcat(logtext, "(nil)");
541                 }
542
543                 log_text(logtext);
544
545                 /* release memory */
546
547                 dump_release(dumpsize);
548         }
549
550         *exceptionptr = xptr;
551
552         return xptr;
553 }
554
555
556
557 /* builtin_canstore ************************************************************
558
559    Checks, if an object can be stored in an array.
560
561    Return value: 1 ... possible
562                  0 ... otherwise
563
564 *******************************************************************************/
565
566 s4 builtin_canstore(java_objectarray *a, java_objectheader *o)
567 {
568         arraydescriptor *desc;
569         arraydescriptor *valuedesc;
570         vftbl_t *componentvftbl;
571         vftbl_t *valuevftbl;
572         int base;
573         castinfo classvalues;
574         
575         if (!o)
576                 return 1;
577
578         /* The following is guaranteed (by verifier checks):
579          *
580          *     *) a->...vftbl->arraydesc != NULL
581          *     *) a->...vftbl->arraydesc->componentvftbl != NULL
582          *     *) o->vftbl is not an interface vftbl
583          */
584         
585         desc = a->header.objheader.vftbl->arraydesc;
586         componentvftbl = desc->componentvftbl;
587         valuevftbl = o->vftbl;
588
589         if ((desc->dimension - 1) == 0) {
590                 s4 res;
591
592                 /* {a is a one-dimensional array} */
593                 /* {a is an array of references} */
594                 
595                 if (valuevftbl == componentvftbl)
596                         return 1;
597
598                 asm_getclassvalues_atomic(componentvftbl, valuevftbl, &classvalues);
599
600                 if ((base = classvalues.super_baseval) <= 0)
601                         /* an array of interface references */
602                         return (valuevftbl->interfacetablelength > -base &&
603                                         valuevftbl->interfacetable[base] != NULL);
604                 
605                 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
606                         <= (unsigned) classvalues.super_diffval;
607
608                 return res;
609         }
610
611         /* {a has dimension > 1} */
612         /* {componentvftbl->arraydesc != NULL} */
613
614         /* check if o is an array */
615         if ((valuedesc = valuevftbl->arraydesc) == NULL)
616                 return 0;
617         /* {o is an array} */
618
619         return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
620 }
621
622
623 /* This is an optimized version where a is guaranteed to be one-dimensional */
624 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
625 {
626         arraydescriptor *desc;
627         vftbl_t *elementvftbl;
628         vftbl_t *valuevftbl;
629         s4 res;
630         int base;
631         castinfo classvalues;
632         
633         if (!o) return 1;
634
635         /* The following is guaranteed (by verifier checks):
636          *
637          *     *) a->...vftbl->arraydesc != NULL
638          *     *) a->...vftbl->arraydesc->elementvftbl != NULL
639          *     *) a->...vftbl->arraydesc->dimension == 1
640          *     *) o->vftbl is not an interface vftbl
641          */
642
643         desc = a->header.objheader.vftbl->arraydesc;
644     elementvftbl = desc->elementvftbl;
645         valuevftbl = o->vftbl;
646
647         /* {a is a one-dimensional array} */
648         
649         if (valuevftbl == elementvftbl)
650                 return 1;
651
652         asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
653
654         if ((base = classvalues.super_baseval) <= 0)
655                 /* an array of interface references */
656                 return (valuevftbl->interfacetablelength > -base &&
657                                 valuevftbl->interfacetable[base] != NULL);
658
659         res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
660                 <= (unsigned) classvalues.super_diffval;
661
662         return res;
663 }
664
665
666 /* This is an optimized version where a is guaranteed to be a
667  * one-dimensional array of a class type */
668 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
669 {
670         vftbl_t *elementvftbl;
671         vftbl_t *valuevftbl;
672         s4 res;
673         castinfo classvalues;
674         
675         if (!o) return 1;
676
677         /* The following is guaranteed (by verifier checks):
678          *
679          *     *) a->...vftbl->arraydesc != NULL
680          *     *) a->...vftbl->arraydesc->elementvftbl != NULL
681          *     *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
682          *     *) a->...vftbl->arraydesc->dimension == 1
683          *     *) o->vftbl is not an interface vftbl
684          */
685
686     elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
687         valuevftbl = o->vftbl;
688
689         /* {a is a one-dimensional array} */
690         
691         if (valuevftbl == elementvftbl)
692                 return 1;
693
694         asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
695
696         res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
697                 <= (unsigned) classvalues.super_diffval;
698
699         return res;
700 }
701
702
703 /* builtin_new *****************************************************************
704
705    Creates a new instance of class c on the heap.
706
707    Return value: pointer to the object or NULL if no memory is
708    available
709                         
710 *******************************************************************************/
711
712 java_objectheader *builtin_new(classinfo *c)
713 {
714         java_objectheader *o;
715
716         /* is the class loaded */
717
718         assert(c->loaded);
719
720         /* is the class linked */
721         if (!c->linked)
722                 if (!link_class(c))
723                         return NULL;
724
725         if (!c->initialized) {
726                 if (initverbose)
727                         log_message_class("Initialize class (from builtin_new): ", c);
728
729                 if (!initialize_class(c))
730                         return NULL;
731         }
732
733         o = heap_allocate(c->instancesize, true, c->finalizer);
734
735         if (!o)
736                 return NULL;
737
738         MSET(o, 0, u1, c->instancesize);
739
740         o->vftbl = c->vftbl;
741
742 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
743         initObjectLock(o);
744 #endif
745
746         return o;
747 }
748
749
750 /* builtin_newarray ************************************************************
751
752    Creates an array with the given vftbl on the heap.
753
754    Return value: pointer to the array or NULL if no memory is available
755
756    CAUTION: The given vftbl must be the vftbl of the *array* class,
757    not of the element class.
758
759 *******************************************************************************/
760
761 java_arrayheader *builtin_newarray(s4 size, vftbl_t *arrayvftbl)
762 {
763         java_arrayheader *a;
764         arraydescriptor *desc;
765         s4 dataoffset;
766         s4 componentsize;
767         s4 actualsize;
768
769         desc = arrayvftbl->arraydesc;
770         dataoffset = desc->dataoffset;
771         componentsize = desc->componentsize;
772
773         if (size < 0) {
774                 *exceptionptr = new_negativearraysizeexception();
775                 return NULL;
776         }
777
778         actualsize = dataoffset + size * componentsize;
779
780         if (((u4) actualsize) < ((u4) size)) { /* overflow */
781                 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
782                 return NULL;
783         }
784
785         a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
786
787         if (!a)
788                 return NULL;
789
790         MSET(a, 0, u1, actualsize);
791
792         a->objheader.vftbl = arrayvftbl;
793
794 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
795         initObjectLock(&a->objheader);
796 #endif
797
798         a->size = size;
799
800         return a;
801 }
802
803
804 /* builtin_anewarray ***********************************************************
805
806    Creates an array of references to the given class type on the heap.
807
808    Return value: pointer to the array or NULL if no memory is
809    available
810
811 *******************************************************************************/
812
813 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
814 {
815         classinfo *c;
816         
817         /* is class loaded */
818         assert(component->loaded);
819
820         /* is class linked */
821         if (!component->linked)
822                 if (!link_class(component))
823                         return NULL;
824
825         c = class_array_of(component, true);
826
827         if (!c)
828                 return NULL;
829
830         return (java_objectarray *) builtin_newarray(size, c->vftbl);
831 }
832
833
834 /* builtin_newarray_int ********************************************************
835
836    Creates an array of 32 bit Integers on the heap.
837
838    Return value: pointer to the array or NULL if no memory is
839    available
840
841 *******************************************************************************/
842
843 java_intarray *builtin_newarray_int(s4 size)
844 {
845         return (java_intarray *)
846                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
847 }
848
849
850 /* builtin_newarray_long *******************************************************
851
852    Creates an array of 64 bit Integers on the heap.
853
854    Return value: pointer to the array or NULL if no memory is
855    available
856
857 *******************************************************************************/
858
859 java_longarray *builtin_newarray_long(s4 size)
860 {
861         return (java_longarray *)
862                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
863 }
864
865
866 /* builtin_newarray_float ******************************************************
867
868    Creates an array of 32 bit IEEE floats on the heap.
869
870    Return value: pointer to the array or NULL if no memory is
871    available
872
873 *******************************************************************************/
874
875 java_floatarray *builtin_newarray_float(s4 size)
876 {
877         return (java_floatarray *)
878                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
879 }
880
881
882 /* builtin_newarray_double *****************************************************
883
884    Creates an array of 64 bit IEEE floats on the heap.
885
886    Return value: pointer to the array or NULL if no memory is
887    available
888
889 *******************************************************************************/
890
891 java_doublearray *builtin_newarray_double(s4 size)
892 {
893         return (java_doublearray *)
894                 builtin_newarray(size,
895                                                  primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
896 }
897
898
899 /* builtin_newarray_byte *******************************************************
900
901    Creates an array of 8 bit Integers on the heap.
902
903    Return value: pointer to the array or NULL if no memory is
904    available
905
906 *******************************************************************************/
907
908 java_bytearray *builtin_newarray_byte(s4 size)
909 {
910         return (java_bytearray *)
911                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
912 }
913
914
915 /* builtin_newarray_char *******************************************************
916
917    Creates an array of characters on the heap.
918
919    Return value: pointer to the array or NULL if no memory is
920    available
921
922 *******************************************************************************/
923
924 java_chararray *builtin_newarray_char(s4 size)
925 {
926         return (java_chararray *)
927                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
928 }
929
930
931 /* builtin_newarray_short ******************************************************
932
933    Creates an array of 16 bit Integers on the heap.
934
935    Return value: pointer to the array or NULL if no memory is
936    available
937
938 *******************************************************************************/
939
940 java_shortarray *builtin_newarray_short(s4 size)
941 {
942         return (java_shortarray *)
943                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
944 }
945
946
947 /* builtin_newarray_boolean ****************************************************
948
949    Creates an array of bytes on the heap. The array is designated as
950    an array of booleans (important for casts)
951         
952    Return value: pointer to the array or NULL if no memory is
953    available
954
955 *******************************************************************************/
956
957 java_booleanarray *builtin_newarray_boolean(s4 size)
958 {
959         return (java_booleanarray *)
960                 builtin_newarray(size,
961                                                  primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
962 }
963
964
965 /* builtin_multianewarray ******************************************************
966
967    Creates a multi-dimensional array on the heap. The dimensions are
968    passed in an array of longs.
969
970    Arguments:
971        n............number of dimensions to create
972        arrayvftbl...vftbl of the array class
973        dims.........array containing the size of each dimension to create
974
975    Return value: pointer to the array or NULL if no memory is
976    available
977
978 ******************************************************************************/
979
980 java_arrayheader *builtin_multianewarray(int n, vftbl_t *arrayvftbl, long *dims)
981 {
982         s4 size, i;
983         java_arrayheader *a;
984         vftbl_t *componentvftbl;
985
986         /* create this dimension */
987
988         size = (s4) dims[0];
989         a = builtin_newarray(size, arrayvftbl);
990
991         if (!a)
992                 return NULL;
993
994         /* if this is the last dimension return */
995
996         if (!--n)
997                 return a;
998
999         /* get the vftbl of the components to create */
1000
1001         componentvftbl = arrayvftbl->arraydesc->componentvftbl;
1002
1003         /* The verifier guarantees that the dimension count is in the range. */
1004
1005         /* create the component arrays */
1006
1007         for (i = 0; i < size; i++) {
1008                 java_arrayheader *ea =
1009 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1010                         /* we save an s4 to a s8 slot, 8-byte aligned */
1011
1012                         builtin_multianewarray(n, componentvftbl, dims + 2);
1013 #else
1014                         builtin_multianewarray(n, componentvftbl, dims + 1);
1015 #endif
1016
1017                 if (!ea)
1018                         return NULL;
1019                 
1020                 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1021         }
1022
1023         return a;
1024 }
1025
1026
1027 /*****************************************************************************
1028                                           METHOD LOGGING
1029
1030         Various functions for printing a message at method entry or exit (for
1031         debugging)
1032         
1033 *****************************************************************************/
1034
1035 u4 methodindent = 0;
1036
1037 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1038                                                                                    methodinfo *m,
1039                                                                                    void *pos,
1040                                                                                    s4 line,
1041                                                                                    s4 noindent)
1042 {
1043         char *logtext;
1044         s4    logtextlen;
1045         s4    dumpsize;
1046
1047         if (opt_verbose || runverbose || verboseexception) {
1048                 /* calculate message length */
1049
1050                 if (xptr) {
1051                         logtextlen =
1052                                 strlen("Exception ") +
1053                                 utf_strlen(xptr->vftbl->class->name);
1054
1055                 } else
1056                         logtextlen = strlen("Some Throwable");
1057
1058                 logtextlen += strlen(" thrown in ");
1059
1060                 if (m) {
1061                         logtextlen +=
1062                                 utf_strlen(m->class->name) +
1063                                 strlen(".") +
1064                                 utf_strlen(m->name) +
1065                                 utf_strlen(m->descriptor) +
1066                                 strlen("(NOSYNC,NATIVE");
1067
1068 #if SIZEOF_VOID_P == 8
1069                         logtextlen +=
1070                                 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1071 #else
1072                         logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1073 #endif
1074
1075                         if (m->class->sourcefile == NULL)
1076                                 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1077                         else
1078                                 logtextlen += utf_strlen(m->class->sourcefile);
1079
1080                         logtextlen += strlen(":65536)");
1081
1082                 } else
1083                         logtextlen += strlen("call_java_method");
1084
1085                 logtextlen += strlen("0");
1086
1087                 /* allocate memory */
1088
1089                 dumpsize = dump_size();
1090
1091                 logtext = DMNEW(char, logtextlen);
1092
1093                 if (xptr) {
1094                         strcpy(logtext, "Exception ");
1095                         utf_strcat_classname(logtext, xptr->vftbl->class->name);
1096
1097                 } else {
1098                         strcpy(logtext, "Some Throwable");
1099                 }
1100
1101                 strcat(logtext, " thrown in ");
1102
1103                 if (m) {
1104                         utf_strcat_classname(logtext, m->class->name);
1105                         strcat(logtext, ".");
1106                         utf_strcat(logtext, m->name);
1107                         utf_strcat(logtext, m->descriptor);
1108
1109                         if (m->flags & ACC_SYNCHRONIZED)
1110                                 strcat(logtext, "(SYNC");
1111                         else
1112                                 strcat(logtext, "(NOSYNC");
1113
1114                         if (m->flags & ACC_NATIVE) {
1115                                 strcat(logtext, ",NATIVE");
1116
1117 #if SIZEOF_VOID_P == 8
1118                                 sprintf(logtext + strlen(logtext),
1119                                                 ")(0x%016lx) at position 0x%016lx",
1120                                                 (ptrint) m->entrypoint, (ptrint) pos);
1121 #else
1122                                 sprintf(logtext + strlen(logtext),
1123                                                 ")(0x%08x) at position 0x%08x",
1124                                                 (ptrint) m->entrypoint, (ptrint) pos);
1125 #endif
1126
1127                         } else {
1128 #if SIZEOF_VOID_P == 8
1129                                 sprintf(logtext + strlen(logtext),
1130                                                 ")(0x%016lx) at position 0x%016lx (",
1131                                                 (ptrint) m->entrypoint, (ptrint) pos);
1132 #else
1133                                 sprintf(logtext + strlen(logtext),
1134                                                 ")(0x%08x) at position 0x%08x (",
1135                                                 (ptrint) m->entrypoint, (ptrint) pos);
1136 #endif
1137
1138                                 if (m->class->sourcefile == NULL)
1139                                         strcat(logtext, "<NO CLASSFILE INFORMATION>");
1140                                 else
1141                                         utf_strcat(logtext, m->class->sourcefile);
1142
1143                                 sprintf(logtext + strlen(logtext), ":%d)", line);
1144                         }
1145
1146                 } else
1147                         strcat(logtext, "call_java_method");
1148
1149                 log_text(logtext);
1150
1151                 /* release memory */
1152
1153                 dump_release(dumpsize);
1154         }
1155
1156         return xptr;
1157 }
1158
1159
1160 /* builtin_trace_args **********************************************************
1161
1162    XXX
1163
1164 *******************************************************************************/
1165
1166 #ifdef TRACE_ARGS_NUM
1167 void builtin_trace_args(s8 a0, s8 a1,
1168 #if TRACE_ARGS_NUM >= 4
1169                                                 s8 a2, s8 a3,
1170 #endif /* TRACE_ARGS_NUM >= 4 */
1171 #if TRACE_ARGS_NUM >= 6
1172                                                 s8 a4, s8 a5,
1173 #endif /* TRACE_ARGS_NUM >= 6 */
1174 #if TRACE_ARGS_NUM == 8
1175                                                 s8 a6, s8 a7,
1176 #endif /* TRACE_ARGS_NUM == 8 */
1177                                                 methodinfo *m)
1178 {
1179         methoddesc *md;
1180         char       *logtext;
1181         s4          logtextlen;
1182         s4          dumpsize;
1183         s4          i;
1184
1185         md = m->parseddesc;
1186
1187         /* calculate message length */
1188
1189         logtextlen =
1190                 methodindent + strlen("called: ") +
1191                 utf_strlen(m->class->name) +
1192                 strlen(".") +
1193                 utf_strlen(m->name) +
1194                 utf_strlen(m->descriptor) +
1195                 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1196
1197         /* add maximal argument length */
1198
1199         logtextlen += strlen("0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, ...(255)");
1200
1201         /* allocate memory */
1202
1203         dumpsize = dump_size();
1204
1205         logtext = DMNEW(char, logtextlen);
1206
1207         for (i = 0; i < methodindent; i++)
1208                 logtext[i] = '\t';
1209
1210         strcpy(logtext + methodindent, "called: ");
1211
1212         utf_strcat_classname(logtext, m->class->name);
1213         strcat(logtext, ".");
1214         utf_strcat(logtext, m->name);
1215         utf_strcat(logtext, m->descriptor);
1216
1217         if (m->flags & ACC_PUBLIC)       strcat(logtext, " PUBLIC");
1218         if (m->flags & ACC_PRIVATE)      strcat(logtext, " PRIVATE");
1219         if (m->flags & ACC_PROTECTED)    strcat(logtext, " PROTECTED");
1220         if (m->flags & ACC_STATIC)       strcat(logtext, " STATIC");
1221         if (m->flags & ACC_FINAL)        strcat(logtext, " FINAL");
1222         if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1223         if (m->flags & ACC_VOLATILE)     strcat(logtext, " VOLATILE");
1224         if (m->flags & ACC_TRANSIENT)    strcat(logtext, " TRANSIENT");
1225         if (m->flags & ACC_NATIVE)       strcat(logtext, " NATIVE");
1226         if (m->flags & ACC_INTERFACE)    strcat(logtext, " INTERFACE");
1227         if (m->flags & ACC_ABSTRACT)     strcat(logtext, " ABSTRACT");
1228
1229         strcat(logtext, "(");
1230
1231         /* xxxprintf ?Bug? an PowerPc Linux (rlwinm.inso)                */
1232         /* Only Arguments in integer Registers are passed correctly here */
1233         /* long longs spilled on Stack have an wrong offset of +4        */
1234         /* So preliminary Bugfix: Only pass 3 params at once to sprintf  */
1235         /* for SIZEOG_VOID_P == 4 && TRACE_ARGS_NUM == 8                 */
1236         switch (md->paramcount) {
1237         case 0:
1238                 break;
1239
1240 #if SIZEOF_VOID_P == 4
1241         case 1:
1242                 sprintf(logtext + strlen(logtext),
1243                                 "0x%llx",
1244                                 a0);
1245                 break;
1246
1247         case 2:
1248                 sprintf(logtext + strlen(logtext),
1249                                 "0x%llx, 0x%llx",
1250                                 a0, a1);
1251                 break;
1252
1253 #if TRACE_ARGS_NUM >= 4
1254         case 3:
1255                 sprintf(logtext + strlen(logtext),
1256                                 "0x%llx, 0x%llx, 0x%llx",
1257                                 a0, a1, a2);
1258                 break;
1259
1260         case 4:
1261                 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1262                                 , a0, a1, a2);
1263                 sprintf(logtext + strlen(logtext), ", 0x%llx", a3);
1264
1265                 break;
1266 #endif /* TRACE_ARGS_NUM >= 4 */
1267
1268 #if TRACE_ARGS_NUM >= 6
1269         case 5:
1270                 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1271                                 , a0, a1, a2);
1272                 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a3, a4);
1273                 break;
1274
1275
1276         case 6:
1277                 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1278                                 , a0, a1, a2);
1279                 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1280                                 , a3, a4, a5);
1281                 break;
1282 #endif /* TRACE_ARGS_NUM >= 6 */
1283
1284 #if TRACE_ARGS_NUM == 8
1285         case 7:
1286                 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1287                                 , a0, a1, a2);
1288                 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1289                                 , a3, a4, a5);
1290                 sprintf(logtext + strlen(logtext), ", 0x%llx", a6);
1291                 break;
1292
1293         case 8:
1294                 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1295                                 , a0, a1, a2);
1296                 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1297                                 , a3, a4, a5);
1298                 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a6, a7);
1299                 break;
1300 #endif /* TRACE_ARGS_NUM == 8 */
1301
1302         default:
1303 #if TRACE_ARGS_NUM == 2
1304                 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, ...(%d)", a0, a1, md->paramcount - 2);
1305
1306 #elif TRACE_ARGS_NUM == 4
1307                 sprintf(logtext + strlen(logtext),
1308                                 "0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1309                                 a0, a1, a2, a3, md->paramcount - 4);
1310
1311 #elif TRACE_ARGS_NUM == 6
1312                 sprintf(logtext + strlen(logtext),
1313                                 "0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1314                                 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1315
1316 #elif TRACE_ARGS_NUM == 8
1317                 sprintf(logtext + strlen(logtext),"0x%llx, 0x%llx, 0x%llx,"
1318                                 , a0, a1, a2);
1319                 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, 0x%llx,"
1320                                 , a3, a4, a5);
1321                 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, ...(%d)"
1322                                 , a6, a7, md->paramcount - 8);
1323 #endif
1324                 break;
1325
1326 #else /* SIZEOF_VOID_P == 4 */
1327
1328         case 1:
1329                 sprintf(logtext + strlen(logtext),
1330                                 "0x%lx",
1331                                 a0);
1332                 break;
1333
1334         case 2:
1335                 sprintf(logtext + strlen(logtext),
1336                                 "0x%lx, 0x%lx",
1337                                 a0, a1);
1338                 break;
1339
1340         case 3:
1341                 sprintf(logtext + strlen(logtext),
1342                                 "0x%lx, 0x%lx, 0x%lx", a0, a1, a2);
1343                 break;
1344
1345         case 4:
1346                 sprintf(logtext + strlen(logtext),
1347                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx",
1348                                 a0, a1, a2, a3);
1349                 break;
1350
1351 #if TRACE_ARGS_NUM >= 6
1352         case 5:
1353                 sprintf(logtext + strlen(logtext),
1354                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1355                                 a0, a1, a2, a3, a4);
1356                 break;
1357
1358         case 6:
1359                 sprintf(logtext + strlen(logtext),
1360                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1361                                 a0, a1, a2, a3, a4, a5);
1362                 break;
1363 #endif /* TRACE_ARGS_NUM >= 6 */
1364
1365 #if TRACE_ARGS_NUM == 8
1366         case 7:
1367                 sprintf(logtext + strlen(logtext),
1368                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1369                                 a0, a1, a2, a3, a4, a5, a6);
1370                 break;
1371
1372         case 8:
1373                 sprintf(logtext + strlen(logtext),
1374                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1375                                 a0, a1, a2, a3, a4, a5, a6, a7);
1376                 break;
1377 #endif /* TRACE_ARGS_NUM == 8 */
1378
1379         default:
1380 #if TRACE_ARGS_NUM == 4
1381                 sprintf(logtext + strlen(logtext),
1382                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1383                                 a0, a1, a2, a3, md->paramcount - 4);
1384
1385 #elif TRACE_ARGS_NUM == 6
1386                 sprintf(logtext + strlen(logtext),
1387                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1388                                 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1389
1390 #elif TRACE_ARGS_NUM == 8
1391                 sprintf(logtext + strlen(logtext),
1392                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1393                                 a0, a1, a2, a3, a4, a5, a6, a7, md->paramcount - 8);
1394 #endif
1395                 break;
1396 #endif /* SIZEOF_VOID_P == 4 */
1397         }
1398
1399         strcat(logtext, ")");
1400
1401         log_text(logtext);
1402
1403         /* release memory */
1404
1405         dump_release(dumpsize);
1406
1407         methodindent++;
1408 }
1409 #endif
1410
1411
1412 /* builtin_displaymethodstop ***************************************************
1413
1414    XXX
1415
1416 *******************************************************************************/
1417
1418 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1419 {
1420         methoddesc *md;
1421         char       *logtext;
1422         s4          logtextlen;
1423         s4          dumpsize;
1424         s4          i;
1425         imm_union   imu;
1426
1427         md = m->parseddesc;
1428
1429         /* calculate message length */
1430
1431         logtextlen =
1432                 methodindent + strlen("finished: ") +
1433                 utf_strlen(m->class->name) +
1434                 strlen(".") +
1435                 utf_strlen(m->name) +
1436                 utf_strlen(m->descriptor) +
1437                 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1438
1439         /* add maximal argument length */
1440
1441         logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1442
1443         /* allocate memory */
1444
1445         dumpsize = dump_size();
1446
1447         logtext = DMNEW(char, logtextlen);
1448
1449         /* generate the message */
1450
1451         for (i = 0; i < methodindent; i++)
1452                 logtext[i] = '\t';
1453
1454         if (methodindent)
1455                 methodindent--;
1456         else
1457                 log_text("WARNING: unmatched methodindent--");
1458
1459         strcpy(logtext + methodindent, "finished: ");
1460         utf_strcat_classname(logtext, m->class->name);
1461         strcat(logtext, ".");
1462         utf_strcat(logtext, m->name);
1463         utf_strcat(logtext, m->descriptor);
1464
1465         switch (md->returntype.type) {
1466         case TYPE_INT:
1467                 sprintf(logtext + strlen(logtext), "->%d (0x%08x)", (s4) l, (s4) l);
1468                 break;
1469
1470         case TYPE_LNG:
1471 #if SIZEOF_VOID_P == 4
1472                 sprintf(logtext + strlen(logtext), "->%lld (0x%016llx)", (s8) l, l);
1473 #else
1474                 sprintf(logtext + strlen(logtext), "->%ld (0x%016lx)", (s8) l, l);
1475 #endif
1476                 break;
1477
1478         case TYPE_ADR:
1479                 sprintf(logtext + strlen(logtext), "->%p", (void *) (ptrint) l);
1480                 break;
1481
1482         case TYPE_FLT:
1483                 imu.f = f;
1484                 sprintf(logtext + strlen(logtext), "->%.8f (0x%08x)", f, imu.i);
1485                 break;
1486
1487         case TYPE_DBL:
1488                 imu.d = d;
1489 #if SIZEOF_VOID_P == 4
1490                 sprintf(logtext + strlen(logtext), "->%.16g (0x%016llx)", d, imu.l);
1491 #else
1492                 sprintf(logtext + strlen(logtext), "->%.16g (0x%016lx)", d, imu.l);
1493 #endif
1494                 break;
1495         }
1496
1497         log_text(logtext);
1498
1499         /* release memory */
1500
1501         dump_release(dumpsize);
1502 }
1503
1504
1505 /****************************************************************************
1506                          SYNCHRONIZATION FUNCTIONS
1507 *****************************************************************************/
1508
1509 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1510 /*
1511  * Lock the mutex of an object.
1512  */
1513 void internal_lock_mutex_for_object(java_objectheader *object)
1514 {
1515         mutexHashEntry *entry;
1516         int hashValue;
1517
1518         assert(object != 0);
1519
1520         hashValue = MUTEX_HASH_VALUE(object);
1521         entry = &mutexHashTable[hashValue];
1522
1523         if (entry->object != 0) {
1524                 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1525                         entry->object = 0;
1526                         entry->mutex.holder = 0;
1527                         entry->mutex.count = 0;
1528                         entry->mutex.muxWaiters = 0;
1529
1530                 } else {
1531                         while (entry->next != 0 && entry->object != object)
1532                                 entry = entry->next;
1533
1534                         if (entry->object != object) {
1535                                 entry->next = firstFreeOverflowEntry;
1536                                 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1537
1538                                 entry = entry->next;
1539                                 entry->object = 0;
1540                                 entry->next = 0;
1541                                 assert(entry->conditionCount == 0);
1542                         }
1543                 }
1544
1545         } else {
1546                 entry->mutex.holder = 0;
1547                 entry->mutex.count = 0;
1548                 entry->mutex.muxWaiters = 0;
1549         }
1550
1551         if (entry->object == 0)
1552                 entry->object = object;
1553         
1554         internal_lock_mutex(&entry->mutex);
1555 }
1556 #endif
1557
1558
1559 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1560 /*
1561  * Unlocks the mutex of an object.
1562  */
1563 void internal_unlock_mutex_for_object (java_objectheader *object)
1564 {
1565         int hashValue;
1566         mutexHashEntry *entry;
1567
1568         hashValue = MUTEX_HASH_VALUE(object);
1569         entry = &mutexHashTable[hashValue];
1570
1571         if (entry->object == object) {
1572                 internal_unlock_mutex(&entry->mutex);
1573
1574         } else {
1575                 while (entry->next != 0 && entry->next->object != object)
1576                         entry = entry->next;
1577
1578                 assert(entry->next != 0);
1579
1580                 internal_unlock_mutex(&entry->next->mutex);
1581
1582                 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1583                         mutexHashEntry *unlinked = entry->next;
1584
1585                         entry->next = unlinked->next;
1586                         unlinked->next = firstFreeOverflowEntry;
1587                         firstFreeOverflowEntry = unlinked;
1588                 }
1589         }
1590 }
1591 #endif
1592
1593
1594 #if defined(USE_THREADS)
1595 void builtin_monitorenter(java_objectheader *o)
1596 {
1597 #if !defined(NATIVE_THREADS)
1598         int hashValue;
1599
1600         ++blockInts;
1601
1602         hashValue = MUTEX_HASH_VALUE(o);
1603         if (mutexHashTable[hashValue].object == o 
1604                 && mutexHashTable[hashValue].mutex.holder == currentThread)
1605                 ++mutexHashTable[hashValue].mutex.count;
1606         else
1607                 internal_lock_mutex_for_object(o);
1608
1609         --blockInts;
1610 #else
1611         monitorEnter((threadobject *) THREADOBJECT, o);
1612 #endif
1613 }
1614 #endif
1615
1616
1617 #if defined(USE_THREADS)
1618 /*
1619  * Locks the class object - needed for static synchronized methods.
1620  * The use_class_as_object call is needed in order to circumvent a
1621  * possible deadlock with builtin_monitorenter called by another
1622  * thread calling use_class_as_object.
1623  */
1624 void builtin_staticmonitorenter(classinfo *c)
1625 {
1626         use_class_as_object(c);
1627         builtin_monitorenter(&c->header);
1628 }
1629 #endif
1630
1631
1632 #if defined(USE_THREADS)
1633 void builtin_monitorexit(java_objectheader *o)
1634 {
1635 #if !defined(NATIVE_THREADS)
1636         int hashValue;
1637
1638         ++blockInts;
1639
1640         hashValue = MUTEX_HASH_VALUE(o);
1641         if (mutexHashTable[hashValue].object == o) {
1642                 if (mutexHashTable[hashValue].mutex.count == 1
1643                         && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1644                         internal_unlock_mutex_for_object(o);
1645                 else
1646                         --mutexHashTable[hashValue].mutex.count;
1647
1648         } else
1649                 internal_unlock_mutex_for_object(o);
1650
1651         --blockInts;
1652 #else
1653         monitorExit((threadobject *) THREADOBJECT, o);
1654 #endif
1655 }
1656 #endif
1657
1658
1659 /*****************************************************************************
1660                           MISCELLANEOUS HELPER FUNCTIONS
1661 *****************************************************************************/
1662
1663
1664
1665 /*********** Functions for integer divisions *****************************
1666  
1667         On some systems (eg. DEC ALPHA), integer division is not supported by the
1668         CPU. These helper functions implement the missing functionality.
1669
1670 ******************************************************************************/
1671
1672 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1673 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1674
1675
1676 /************** Functions for long arithmetics *******************************
1677
1678         On systems where 64 bit Integers are not supported by the CPU, these
1679         functions are needed.
1680
1681 ******************************************************************************/
1682
1683 s8 builtin_ladd(s8 a, s8 b)
1684 {
1685         s8 c;
1686
1687 #if U8_AVAILABLE
1688         c = a + b; 
1689 #else
1690         c = builtin_i2l(0);
1691 #endif
1692
1693         return c;
1694 }
1695
1696 s8 builtin_lsub(s8 a, s8 b) 
1697 {
1698         s8 c;
1699
1700 #if U8_AVAILABLE
1701         c = a - b; 
1702 #else
1703         c = builtin_i2l(0);
1704 #endif
1705
1706         return c;
1707 }
1708
1709 s8 builtin_lmul(s8 a, s8 b) 
1710 {
1711         s8 c;
1712
1713 #if U8_AVAILABLE
1714         c = a * b; 
1715 #else
1716         c = builtin_i2l(0);
1717 #endif
1718
1719         return c;
1720 }
1721
1722 s8 builtin_ldiv(s8 a, s8 b) 
1723 {
1724         s8 c;
1725
1726 #if U8_AVAILABLE
1727         c = a / b; 
1728 #else
1729         c = builtin_i2l(0);
1730 #endif
1731
1732         return c;
1733 }
1734
1735 s8 builtin_lrem(s8 a, s8 b) 
1736 {
1737         s8 c;
1738
1739 #if U8_AVAILABLE
1740         c = a % b; 
1741 #else
1742         c = builtin_i2l(0);
1743 #endif
1744
1745         return c;
1746 }
1747
1748 s8 builtin_lshl(s8 a, s4 b) 
1749 {
1750         s8 c;
1751
1752 #if U8_AVAILABLE
1753         c = a << (b & 63);
1754 #else
1755         c = builtin_i2l(0);
1756 #endif
1757
1758         return c;
1759 }
1760
1761 s8 builtin_lshr(s8 a, s4 b) 
1762 {
1763         s8 c;
1764
1765 #if U8_AVAILABLE
1766         c = a >> (b & 63);
1767 #else
1768         c = builtin_i2l(0);
1769 #endif
1770
1771         return c;
1772 }
1773
1774 s8 builtin_lushr(s8 a, s4 b) 
1775 {
1776         s8 c;
1777
1778 #if U8_AVAILABLE
1779         c = ((u8) a) >> (b & 63);
1780 #else
1781         c = builtin_i2l(0);
1782 #endif
1783
1784         return c;
1785 }
1786
1787 s8 builtin_land(s8 a, s8 b) 
1788 {
1789         s8 c;
1790
1791 #if U8_AVAILABLE
1792         c = a & b; 
1793 #else
1794         c = builtin_i2l(0);
1795 #endif
1796
1797         return c;
1798 }
1799
1800 s8 builtin_lor(s8 a, s8 b) 
1801 {
1802         s8 c;
1803
1804 #if U8_AVAILABLE
1805         c = a | b; 
1806 #else
1807         c = builtin_i2l(0);
1808 #endif
1809
1810         return c;
1811 }
1812
1813 s8 builtin_lxor(s8 a, s8 b) 
1814 {
1815         s8 c;
1816
1817 #if U8_AVAILABLE
1818         c = a ^ b; 
1819 #else
1820         c = builtin_i2l(0);
1821 #endif
1822
1823         return c;
1824 }
1825
1826 s8 builtin_lneg(s8 a) 
1827 {
1828         s8 c;
1829
1830 #if U8_AVAILABLE
1831         c = -a;
1832 #else
1833         c = builtin_i2l(0);
1834 #endif
1835
1836         return c;
1837 }
1838
1839 s4 builtin_lcmp(s8 a, s8 b) 
1840
1841 #if U8_AVAILABLE
1842         if (a < b) return -1;
1843         if (a > b) return 1;
1844         return 0;
1845 #else
1846         return 0;
1847 #endif
1848 }
1849
1850
1851
1852
1853
1854 /*********** Functions for floating point operations *************************/
1855
1856 /* used to convert FLT_xxx defines into float values */
1857
1858 static inline float intBitsToFloat(s4 i)
1859 {
1860         imm_union imb;
1861
1862         imb.i = i;
1863         return imb.f;
1864 }
1865
1866
1867 /* used to convert DBL_xxx defines into double values */
1868
1869 static inline float longBitsToDouble(s8 l)
1870 {
1871         imm_union imb;
1872
1873         imb.l = l;
1874         return imb.d;
1875 }
1876
1877
1878 float builtin_fadd(float a, float b)
1879 {
1880         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1881         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1882         if (finitef(a)) {
1883                 if (finitef(b))
1884                         return a + b;
1885                 else
1886                         return b;
1887         }
1888         else {
1889                 if (finitef(b))
1890                         return a;
1891                 else {
1892                         if (copysignf(1.0, a) == copysignf(1.0, b))
1893                                 return a;
1894                         else
1895                                 return intBitsToFloat(FLT_NAN);
1896                 }
1897         }
1898 }
1899
1900
1901 float builtin_fsub(float a, float b)
1902 {
1903         return builtin_fadd(a, builtin_fneg(b));
1904 }
1905
1906
1907 float builtin_fmul(float a, float b)
1908 {
1909         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1910         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1911         if (finitef(a)) {
1912                 if (finitef(b)) return a * b;
1913                 else {
1914                         if (a == 0) return intBitsToFloat(FLT_NAN);
1915                         else return copysignf(b, copysignf(1.0, b)*a);
1916                 }
1917         }
1918         else {
1919                 if (finitef(b)) {
1920                         if (b == 0) return intBitsToFloat(FLT_NAN);
1921                         else return copysignf(a, copysignf(1.0, a)*b);
1922                 }
1923                 else {
1924                         return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1925                 }
1926         }
1927 }
1928
1929
1930 /* builtin_ddiv ****************************************************************
1931
1932    Implementation as described in VM Spec.
1933
1934 *******************************************************************************/
1935
1936 float builtin_fdiv(float a, float b)
1937 {
1938         if (finitef(a)) {
1939                 if (finitef(b)) {
1940                         /* If neither value1' nor value2' is NaN, the sign of the result */
1941                         /* is positive if both values have the same sign, negative if the */
1942                         /* values have different signs. */
1943
1944                         return a / b;
1945
1946                 } else {
1947                         if (isnanf(b)) {
1948                                 /* If either value1' or value2' is NaN, the result is NaN. */
1949
1950                                 return intBitsToFloat(FLT_NAN);
1951
1952                         } else {
1953                                 /* Division of a finite value by an infinity results in a */
1954                                 /* signed zero, with the sign-producing rule just given. */
1955
1956                                 /* is sign equal? */
1957
1958                                 if (copysignf(1.0, a) == copysignf(1.0, b))
1959                                         return 0.0;
1960                                 else
1961                                         return -0.0;
1962                         }
1963                 }
1964
1965         } else {
1966                 if (isnanf(a)) {
1967                         /* If either value1' or value2' is NaN, the result is NaN. */
1968
1969                         return intBitsToFloat(FLT_NAN);
1970
1971                 } else if (finitef(b)) {
1972                         /* Division of an infinity by a finite value results in a signed */
1973                         /* infinity, with the sign-producing rule just given. */
1974
1975                         /* is sign equal? */
1976
1977                         if (copysignf(1.0, a) == copysignf(1.0, b))
1978                                 return intBitsToFloat(FLT_POSINF);
1979                         else
1980                                 return intBitsToFloat(FLT_NEGINF);
1981
1982                 } else {
1983                         /* Division of an infinity by an infinity results in NaN. */
1984
1985                         return intBitsToFloat(FLT_NAN);
1986                 }
1987         }
1988 }
1989
1990
1991 float builtin_frem(float a, float b)
1992 {
1993         return fmodf(a, b);
1994 }
1995
1996
1997 float builtin_fneg(float a)
1998 {
1999         if (isnanf(a)) return a;
2000         else {
2001                 if (finitef(a)) return -a;
2002                 else return copysignf(a, -copysignf(1.0, a));
2003         }
2004 }
2005
2006
2007 s4 builtin_fcmpl(float a, float b)
2008 {
2009         if (isnanf(a)) return -1;
2010         if (isnanf(b)) return -1;
2011         if (!finitef(a) || !finitef(b)) {
2012                 a = finitef(a) ? 0 : copysignf(1.0,     a);
2013                 b = finitef(b) ? 0 : copysignf(1.0, b);
2014         }
2015         if (a > b) return 1;
2016         if (a == b) return 0;
2017         return -1;
2018 }
2019
2020
2021 s4 builtin_fcmpg(float a, float b)
2022 {
2023         if (isnanf(a)) return 1;
2024         if (isnanf(b)) return 1;
2025         if (!finitef(a) || !finitef(b)) {
2026                 a = finitef(a) ? 0 : copysignf(1.0, a);
2027                 b = finitef(b) ? 0 : copysignf(1.0, b);
2028         }
2029         if (a > b) return 1;
2030         if (a == b) return 0;
2031         return -1;
2032 }
2033
2034
2035
2036 /************************* Functions for doubles ****************************/
2037
2038 double builtin_dadd(double a, double b)
2039 {
2040         if (isnan(a)) return longBitsToDouble(DBL_NAN);
2041         if (isnan(b)) return longBitsToDouble(DBL_NAN);
2042         if (finite(a)) {
2043                 if (finite(b)) return a + b;
2044                 else return b;
2045         }
2046         else {
2047                 if (finite(b)) return a;
2048                 else {
2049                         if (copysign(1.0, a)==copysign(1.0, b)) return a;
2050                         else return longBitsToDouble(DBL_NAN);
2051                 }
2052         }
2053 }
2054
2055
2056 double builtin_dsub(double a, double b)
2057 {
2058         return builtin_dadd(a, builtin_dneg(b));
2059 }
2060
2061
2062 double builtin_dmul(double a, double b)
2063 {
2064         if (isnan(a)) return longBitsToDouble(DBL_NAN);
2065         if (isnan(b)) return longBitsToDouble(DBL_NAN);
2066         if (finite(a)) {
2067                 if (finite(b)) return a * b;
2068                 else {
2069                         if (a == 0) return longBitsToDouble(DBL_NAN);
2070                         else return copysign(b, copysign(1.0, b) * a);
2071                 }
2072         }
2073         else {
2074                 if (finite(b)) {
2075                         if (b == 0) return longBitsToDouble(DBL_NAN);
2076                         else return copysign(a, copysign(1.0, a) * b);
2077                 }
2078                 else {
2079                         return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2080                 }
2081         }
2082 }
2083
2084
2085 /* builtin_ddiv ****************************************************************
2086
2087    Implementation as described in VM Spec.
2088
2089 *******************************************************************************/
2090
2091 double builtin_ddiv(double a, double b)
2092 {
2093         if (finite(a)) {
2094                 if (finite(b)) {
2095                         /* If neither value1' nor value2' is NaN, the sign of the result */
2096                         /* is positive if both values have the same sign, negative if the */
2097                         /* values have different signs. */
2098
2099                         return a / b;
2100
2101                 } else {
2102                         if (isnan(b)) {
2103                                 /* If either value1' or value2' is NaN, the result is NaN. */
2104
2105                                 return longBitsToDouble(DBL_NAN);
2106
2107                         } else {
2108                                 /* Division of a finite value by an infinity results in a */
2109                                 /* signed zero, with the sign-producing rule just given. */
2110
2111                                 /* is sign equal? */
2112
2113                                 if (copysign(1.0, a) == copysign(1.0, b))
2114                                         return 0.0;
2115                                 else
2116                                         return -0.0;
2117                         }
2118                 }
2119
2120         } else {
2121                 if (isnan(a)) {
2122                         /* If either value1' or value2' is NaN, the result is NaN. */
2123
2124                         return longBitsToDouble(DBL_NAN);
2125
2126                 } else if (finite(b)) {
2127                         /* Division of an infinity by a finite value results in a signed */
2128                         /* infinity, with the sign-producing rule just given. */
2129
2130                         /* is sign equal? */
2131
2132                         if (copysign(1.0, a) == copysign(1.0, b))
2133                                 return longBitsToDouble(DBL_POSINF);
2134                         else
2135                                 return longBitsToDouble(DBL_NEGINF);
2136
2137                 } else {
2138                         /* Division of an infinity by an infinity results in NaN. */
2139
2140                         return longBitsToDouble(DBL_NAN);
2141                 }
2142         }
2143 }
2144
2145
2146 double builtin_drem(double a, double b)
2147 {
2148         return fmod(a, b);
2149 }
2150
2151 /* builtin_dneg ****************************************************************
2152
2153    Implemented as described in VM Spec.
2154
2155 *******************************************************************************/
2156
2157 double builtin_dneg(double a)
2158 {
2159         if (isnan(a)) {
2160                 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2161                 /* sign). */
2162
2163                 return a;
2164
2165         } else {
2166                 if (finite(a)) {
2167                         /* If the operand is a zero, the result is the zero of opposite */
2168                         /* sign. */
2169
2170                         return -a;
2171
2172                 } else {
2173                         /* If the operand is an infinity, the result is the infinity of */
2174                         /* opposite sign. */
2175
2176                         return copysign(a, -copysign(1.0, a));
2177                 }
2178         }
2179 }
2180
2181
2182 s4 builtin_dcmpl(double a, double b)
2183 {
2184         if (isnan(a)) return -1;
2185         if (isnan(b)) return -1;
2186         if (!finite(a) || !finite(b)) {
2187                 a = finite(a) ? 0 : copysign(1.0, a);
2188                 b = finite(b) ? 0 : copysign(1.0, b);
2189         }
2190         if (a > b) return 1;
2191         if (a == b) return 0;
2192         return -1;
2193 }
2194
2195
2196 s4 builtin_dcmpg(double a, double b)
2197 {
2198         if (isnan(a)) return 1;
2199         if (isnan(b)) return 1;
2200         if (!finite(a) || !finite(b)) {
2201                 a = finite(a) ? 0 : copysign(1.0, a);
2202                 b = finite(b) ? 0 : copysign(1.0, b);
2203         }
2204         if (a > b) return 1;
2205         if (a == b) return 0;
2206         return -1;
2207 }
2208
2209
2210 /*********************** Conversion operations ****************************/
2211
2212 s8 builtin_i2l(s4 i)
2213 {
2214 #if U8_AVAILABLE
2215         return i;
2216 #else
2217         s8 v;
2218         v.high = 0;
2219         v.low = i;
2220         return v;
2221 #endif
2222 }
2223
2224
2225 float builtin_i2f(s4 a)
2226 {
2227         float f = (float) a;
2228         return f;
2229 }
2230
2231
2232 double builtin_i2d(s4 a)
2233 {
2234         double d = (double) a;
2235         return d;
2236 }
2237
2238
2239 s4 builtin_l2i(s8 l)
2240 {
2241 #if U8_AVAILABLE
2242         return (s4) l;
2243 #else
2244         return l.low;
2245 #endif
2246 }
2247
2248
2249 float builtin_l2f(s8 a)
2250 {
2251 #if U8_AVAILABLE
2252         float f = (float) a;
2253         return f;
2254 #else
2255         return 0.0;
2256 #endif
2257 }
2258
2259
2260 double builtin_l2d(s8 a)
2261 {
2262 #if U8_AVAILABLE
2263         double d = (double) a;
2264         return d;
2265 #else
2266         return 0.0;
2267 #endif
2268 }
2269
2270
2271 s4 builtin_f2i(float a) 
2272 {
2273         s4 i;
2274
2275         i = builtin_d2i((double) a);
2276
2277         return i;
2278
2279         /*      float f;
2280         
2281                 if (isnanf(a))
2282                 return 0;
2283                 if (finitef(a)) {
2284                 if (a > 2147483647)
2285                 return 2147483647;
2286                 if (a < (-2147483648))
2287                 return (-2147483648);
2288                 return (s4) a;
2289                 }
2290                 f = copysignf((float) 1.0, a);
2291                 if (f > 0)
2292                 return 2147483647;
2293                 return (-2147483648); */
2294 }
2295
2296
2297 s8 builtin_f2l(float a)
2298 {
2299         s8 l;
2300
2301         l = builtin_d2l((double) a);
2302
2303         return l;
2304
2305         /*      float f;
2306         
2307                 if (finitef(a)) {
2308                 if (a > 9223372036854775807L)
2309                 return 9223372036854775807L;
2310                 if (a < (-9223372036854775808L))
2311                 return (-9223372036854775808L);
2312                 return (s8) a;
2313                 }
2314                 if (isnanf(a))
2315                 return 0;
2316                 f = copysignf((float) 1.0, a);
2317                 if (f > 0)
2318                 return 9223372036854775807L;
2319                 return (-9223372036854775808L); */
2320 }
2321
2322
2323 double builtin_f2d(float a)
2324 {
2325         if (finitef(a)) return (double) a;
2326         else {
2327                 if (isnanf(a))
2328                         return longBitsToDouble(DBL_NAN);
2329                 else
2330                         return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2331         }
2332 }
2333
2334
2335 s4 builtin_d2i(double a) 
2336
2337         double d;
2338         
2339         if (finite(a)) {
2340                 if (a >= 2147483647)
2341                         return 2147483647;
2342                 if (a <= (-2147483647-1))
2343                         return (-2147483647-1);
2344                 return (s4) a;
2345         }
2346         if (isnan(a))
2347                 return 0;
2348         d = copysign(1.0, a);
2349         if (d > 0)
2350                 return 2147483647;
2351         return (-2147483647-1);
2352 }
2353
2354
2355 s8 builtin_d2l(double a)
2356 {
2357         double d;
2358         
2359         if (finite(a)) {
2360                 if (a >= 9223372036854775807LL)
2361                         return 9223372036854775807LL;
2362                 if (a <= (-9223372036854775807LL-1))
2363                         return (-9223372036854775807LL-1);
2364                 return (s8) a;
2365         }
2366         if (isnan(a))
2367                 return 0;
2368         d = copysign(1.0, a);
2369         if (d > 0)
2370                 return 9223372036854775807LL;
2371         return (-9223372036854775807LL-1);
2372 }
2373
2374
2375 float builtin_d2f(double a)
2376 {
2377         if (finite(a))
2378                 return (float) a;
2379         else {
2380                 if (isnan(a))
2381                         return intBitsToFloat(FLT_NAN);
2382                 else
2383                         return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2384         }
2385 }
2386
2387
2388 /* builtin_clone_array *********************************************************
2389
2390    Wrapper function for cloning arrays.
2391
2392 *******************************************************************************/
2393
2394 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
2395 {
2396         java_arrayheader    *ah;
2397         java_lang_Cloneable *c;
2398
2399         c = (java_lang_Cloneable *) o;
2400
2401         ah = (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, c);
2402
2403         return ah;
2404 }
2405
2406
2407 /* builtin_asm_get_exceptionptrptr *********************************************
2408
2409    this is a wrapper for calls from asmpart
2410
2411 *******************************************************************************/
2412
2413 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2414 java_objectheader **builtin_asm_get_exceptionptrptr(void)
2415 {
2416         return builtin_get_exceptionptrptr();
2417 }
2418 #endif
2419
2420
2421 /*
2422  * These are local overrides for various environment variables in Emacs.
2423  * Please do not remove this and leave it at the end of the file, where
2424  * Emacs will automagically detect them.
2425  * ---------------------------------------------------------------------
2426  * Local variables:
2427  * mode: c
2428  * indent-tabs-mode: t
2429  * c-basic-offset: 4
2430  * tab-width: 4
2431  * End:
2432  */