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