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