* Only added some debug output for mips and powerpc, this should be remove
[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 3562 2005-11-04 16:20:54Z twisti $
40
41 */
42
43
44 #include <assert.h>
45 #include <stdlib.h>
46 #include <string.h>
47
48 #include "config.h"
49 #include "vm/types.h"
50
51 #include "arch.h"
52 #include "md-abi.h"
53
54 #include "fdlibm/fdlibm.h"
55
56 #include "mm/boehm.h"
57 #include "mm/memory.h"
58 #include "native/native.h"
59 #include "native/include/java_lang_Cloneable.h"
60 #include "native/include/java_lang_Object.h"          /* required by VMObject */
61 #include "native/include/java_lang_VMObject.h"
62 #include "native/include/java_lang_Throwable.h"
63 #include "native/include/java_lang_VMThrowable.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/exceptions.h"
78 #include "vm/global.h"
79 #include "vm/initialize.h"
80 #include "vm/loader.h"
81 #include "vm/options.h"
82 #include "vm/stringlocal.h"
83 #include "vm/tables.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 java_objectheader *builtin_throw_exception(java_objectheader *xptr)
507 {
508     java_lang_Throwable *t;
509         char                *logtext;
510         s4                   logtextlen;
511         s4                   dumpsize;
512
513         if (opt_verbose) {
514                 t = (java_lang_Throwable *) xptr;
515
516                 /* calculate message length */
517
518                 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
519
520                 if (t) {
521                         logtextlen +=
522                                 utf_strlen(xptr->vftbl->class->name) +
523                                 strlen(": ") +
524                                 javastring_strlen((java_objectheader *) t->detailMessage);
525
526                 } else
527                         logtextlen += strlen("(nil)");
528
529                 /* allocate memory */
530
531                 dumpsize = dump_size();
532
533                 logtext = DMNEW(char, logtextlen);
534
535                 strcpy(logtext, "Builtin exception thrown: ");
536
537                 if (t) {
538                         utf_sprint_classname(logtext + strlen(logtext),
539                                                                  xptr->vftbl->class->name);
540
541                         if (t->detailMessage) {
542                                 char *buf;
543
544                                 buf = javastring_tochar((java_objectheader *) t->detailMessage);
545                                 strcat(logtext, ": ");
546                                 strcat(logtext, buf);
547                                 MFREE(buf, char, strlen(buf));
548                         }
549
550                 } else {
551                         strcat(logtext, "(nil)");
552                 }
553
554                 log_text(logtext);
555
556                 /* release memory */
557
558                 dump_release(dumpsize);
559         }
560
561         *exceptionptr = xptr;
562
563         return xptr;
564 }
565
566
567
568 /* builtin_canstore ************************************************************
569
570    Checks, if an object can be stored in an array.
571
572    Return value: 1 ... possible
573                  0 ... otherwise
574
575 *******************************************************************************/
576
577 s4 builtin_canstore(java_objectarray *a, java_objectheader *o)
578 {
579         arraydescriptor *desc;
580         arraydescriptor *valuedesc;
581         vftbl_t *componentvftbl;
582         vftbl_t *valuevftbl;
583         int base;
584         castinfo classvalues;
585         
586         if (!o)
587                 return 1;
588
589         /* The following is guaranteed (by verifier checks):
590          *
591          *     *) a->...vftbl->arraydesc != NULL
592          *     *) a->...vftbl->arraydesc->componentvftbl != NULL
593          *     *) o->vftbl is not an interface vftbl
594          */
595         
596         desc = a->header.objheader.vftbl->arraydesc;
597         componentvftbl = desc->componentvftbl;
598         valuevftbl = o->vftbl;
599
600         if ((desc->dimension - 1) == 0) {
601                 s4 res;
602
603                 /* {a is a one-dimensional array} */
604                 /* {a is an array of references} */
605                 
606                 if (valuevftbl == componentvftbl)
607                         return 1;
608
609                 asm_getclassvalues_atomic(componentvftbl, valuevftbl, &classvalues);
610
611                 if ((base = classvalues.super_baseval) <= 0)
612                         /* an array of interface references */
613                         return (valuevftbl->interfacetablelength > -base &&
614                                         valuevftbl->interfacetable[base] != NULL);
615                 
616                 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
617                         <= (unsigned) classvalues.super_diffval;
618
619                 return res;
620         }
621
622         /* {a has dimension > 1} */
623         /* {componentvftbl->arraydesc != NULL} */
624
625         /* check if o is an array */
626         if ((valuedesc = valuevftbl->arraydesc) == NULL)
627                 return 0;
628         /* {o is an array} */
629
630         return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
631 }
632
633
634 /* This is an optimized version where a is guaranteed to be one-dimensional */
635 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
636 {
637         arraydescriptor *desc;
638         vftbl_t *elementvftbl;
639         vftbl_t *valuevftbl;
640         s4 res;
641         int base;
642         castinfo classvalues;
643         
644         if (!o) return 1;
645
646         /* The following is guaranteed (by verifier checks):
647          *
648          *     *) a->...vftbl->arraydesc != NULL
649          *     *) a->...vftbl->arraydesc->elementvftbl != NULL
650          *     *) a->...vftbl->arraydesc->dimension == 1
651          *     *) o->vftbl is not an interface vftbl
652          */
653
654         desc = a->header.objheader.vftbl->arraydesc;
655     elementvftbl = desc->elementvftbl;
656         valuevftbl = o->vftbl;
657
658         /* {a is a one-dimensional array} */
659         
660         if (valuevftbl == elementvftbl)
661                 return 1;
662
663         asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
664
665         if ((base = classvalues.super_baseval) <= 0)
666                 /* an array of interface references */
667                 return (valuevftbl->interfacetablelength > -base &&
668                                 valuevftbl->interfacetable[base] != NULL);
669
670         res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
671                 <= (unsigned) classvalues.super_diffval;
672
673         return res;
674 }
675
676
677 /* This is an optimized version where a is guaranteed to be a
678  * one-dimensional array of a class type */
679 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
680 {
681         vftbl_t *elementvftbl;
682         vftbl_t *valuevftbl;
683         s4 res;
684         castinfo classvalues;
685         
686         if (!o) return 1;
687
688         /* The following is guaranteed (by verifier checks):
689          *
690          *     *) a->...vftbl->arraydesc != NULL
691          *     *) a->...vftbl->arraydesc->elementvftbl != NULL
692          *     *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
693          *     *) a->...vftbl->arraydesc->dimension == 1
694          *     *) o->vftbl is not an interface vftbl
695          */
696
697     elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
698         valuevftbl = o->vftbl;
699
700         /* {a is a one-dimensional array} */
701         
702         if (valuevftbl == elementvftbl)
703                 return 1;
704
705         asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
706
707         res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
708                 <= (unsigned) classvalues.super_diffval;
709
710         return res;
711 }
712
713
714 /* builtin_new *****************************************************************
715
716    Creates a new instance of class c on the heap.
717
718    Return value: pointer to the object or NULL if no memory is
719    available
720                         
721 *******************************************************************************/
722
723 java_objectheader *builtin_new(classinfo *c)
724 {
725         java_objectheader *o;
726
727         /* is the class loaded */
728
729         assert(c->loaded);
730
731         /* is the class linked */
732         if (!c->linked)
733                 if (!link_class(c))
734                         return NULL;
735
736         if (!c->initialized) {
737                 if (initverbose)
738                         log_message_class("Initialize class (from builtin_new): ", c);
739
740                 if (!initialize_class(c))
741                         return NULL;
742         }
743
744         o = heap_allocate(c->instancesize, true, c->finalizer);
745
746         if (!o)
747                 return NULL;
748
749         o->vftbl = c->vftbl;
750
751 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
752         initObjectLock(o);
753 #endif
754
755         return o;
756 }
757
758
759 /* builtin_newarray ************************************************************
760
761    Creates an array with the given vftbl on the heap. This function
762    takes as class argument an array class.
763
764    Return value: pointer to the array or NULL if no memory is available
765
766 *******************************************************************************/
767
768 java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
769 {
770         arraydescriptor  *desc;
771         s4                dataoffset;
772         s4                componentsize;
773         s4                actualsize;
774         java_arrayheader *a;
775
776         desc          = arrayclass->vftbl->arraydesc;
777         dataoffset    = desc->dataoffset;
778         componentsize = desc->componentsize;
779
780         if (size < 0) {
781                 *exceptionptr = new_negativearraysizeexception();
782                 return NULL;
783         }
784
785         actualsize = dataoffset + size * componentsize;
786
787         if (((u4) actualsize) < ((u4) size)) { /* overflow */
788                 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
789                 return NULL;
790         }
791
792         a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
793
794         if (!a)
795                 return NULL;
796
797         a->objheader.vftbl = arrayclass->vftbl;
798
799 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
800         initObjectLock(&a->objheader);
801 #endif
802
803         a->size = size;
804
805         return a;
806 }
807
808
809 /* builtin_anewarray ***********************************************************
810
811    Creates an array of references to the given class type on the heap.
812
813    Return value: pointer to the array or NULL if no memory is
814    available
815
816 *******************************************************************************/
817
818 java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
819 {
820         classinfo *arrayclass;
821         
822         /* is class loaded */
823
824         assert(componentclass->loaded);
825
826         /* is class linked */
827
828         if (!componentclass->linked)
829                 if (!link_class(componentclass))
830                         return NULL;
831
832         arrayclass = class_array_of(componentclass, true);
833
834         if (!arrayclass)
835                 return NULL;
836
837         return (java_objectarray *) builtin_newarray(size, arrayclass);
838 }
839
840
841 /* builtin_newarray_boolean ****************************************************
842
843    Creates an array of bytes on the heap. The array is designated as
844    an array of booleans (important for casts)
845         
846    Return value: pointer to the array or NULL if no memory is
847    available
848
849 *******************************************************************************/
850
851 java_booleanarray *builtin_newarray_boolean(s4 size)
852 {
853         return (java_booleanarray *)
854                 builtin_newarray(size,
855                                                  primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
856 }
857
858
859 /* builtin_newarray_byte *******************************************************
860
861    Creates an array of 8 bit Integers on the heap.
862
863    Return value: pointer to the array or NULL if no memory is
864    available
865
866 *******************************************************************************/
867
868 java_bytearray *builtin_newarray_byte(s4 size)
869 {
870         return (java_bytearray *)
871                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
872 }
873
874
875 /* builtin_newarray_char *******************************************************
876
877    Creates an array of characters on the heap.
878
879    Return value: pointer to the array or NULL if no memory is
880    available
881
882 *******************************************************************************/
883
884 java_chararray *builtin_newarray_char(s4 size)
885 {
886         return (java_chararray *)
887                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
888 }
889
890
891 /* builtin_newarray_short ******************************************************
892
893    Creates an array of 16 bit Integers on the heap.
894
895    Return value: pointer to the array or NULL if no memory is
896    available
897
898 *******************************************************************************/
899
900 java_shortarray *builtin_newarray_short(s4 size)
901 {
902         return (java_shortarray *)
903                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
904 }
905
906
907 /* builtin_newarray_int ********************************************************
908
909    Creates an array of 32 bit Integers on the heap.
910
911    Return value: pointer to the array or NULL if no memory is
912    available
913
914 *******************************************************************************/
915
916 java_intarray *builtin_newarray_int(s4 size)
917 {
918         return (java_intarray *)
919                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
920 }
921
922
923 /* builtin_newarray_long *******************************************************
924
925    Creates an array of 64 bit Integers on the heap.
926
927    Return value: pointer to the array or NULL if no memory is
928    available
929
930 *******************************************************************************/
931
932 java_longarray *builtin_newarray_long(s4 size)
933 {
934         return (java_longarray *)
935                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
936 }
937
938
939 /* builtin_newarray_float ******************************************************
940
941    Creates an array of 32 bit IEEE floats on the heap.
942
943    Return value: pointer to the array or NULL if no memory is
944    available
945
946 *******************************************************************************/
947
948 java_floatarray *builtin_newarray_float(s4 size)
949 {
950         return (java_floatarray *)
951                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
952 }
953
954
955 /* builtin_newarray_double *****************************************************
956
957    Creates an array of 64 bit IEEE floats on the heap.
958
959    Return value: pointer to the array or NULL if no memory is
960    available
961
962 *******************************************************************************/
963
964 java_doublearray *builtin_newarray_double(s4 size)
965 {
966         return (java_doublearray *)
967                 builtin_newarray(size,
968                                                  primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
969 }
970
971
972 /* builtin_multianewarray_intern ***********************************************
973
974    Creates a multi-dimensional array on the heap. The dimensions are
975    passed in an array of longs.
976
977    Arguments:
978        n............number of dimensions to create
979        arrayvftbl...vftbl of the array class
980        dims.........array containing the size of each dimension to create
981
982    Return value: pointer to the array or NULL if no memory is
983    available
984
985 ******************************************************************************/
986
987 static java_arrayheader *builtin_multianewarray_intern(int n,
988                                                                                                            classinfo *arrayclass,
989                                                                                                            long *dims)
990 {
991         s4                size;
992         java_arrayheader *a;
993         classinfo        *componentclass;
994         s4                i;
995
996         /* create this dimension */
997
998         size = (s4) dims[0];
999         a = builtin_newarray(size, arrayclass);
1000
1001         if (!a)
1002                 return NULL;
1003
1004         /* if this is the last dimension return */
1005
1006         if (!--n)
1007                 return a;
1008
1009         /* get the class of the components to create */
1010
1011         componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1012
1013         /* The verifier guarantees that the dimension count is in the range. */
1014
1015         /* create the component arrays */
1016
1017         for (i = 0; i < size; i++) {
1018                 java_arrayheader *ea =
1019 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1020                         /* we save an s4 to a s8 slot, 8-byte aligned */
1021
1022                         builtin_multianewarray_intern(n, componentclass, dims + 2);
1023 #else
1024                         builtin_multianewarray_intern(n, componentclass, dims + 1);
1025 #endif
1026
1027                 if (!ea)
1028                         return NULL;
1029                 
1030                 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1031         }
1032
1033         return a;
1034 }
1035
1036
1037 /* builtin_multianewarray ******************************************************
1038
1039    Wrapper for builtin_multianewarray_intern which checks all
1040    dimensions before we start allocating.
1041
1042 ******************************************************************************/
1043
1044 java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
1045                                                                                  long *dims)
1046 {
1047         s4 i;
1048         s4 size;
1049
1050         /* check all dimensions before doing anything */
1051
1052         for (i = 0; i < n; i++) {
1053 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1054                 /* we save an s4 to a s8 slot, 8-byte aligned */
1055                 size = (s4) dims[i * 2];
1056 #else
1057                 size = (s4) dims[i];
1058 #endif
1059
1060                 if (size < 0) {
1061                         *exceptionptr = new_negativearraysizeexception();
1062                         return NULL;
1063                 }
1064         }
1065
1066         /* now call the real function */
1067
1068         return builtin_multianewarray_intern(n, arrayclass, dims);
1069 }
1070
1071
1072 /*****************************************************************************
1073                                           METHOD LOGGING
1074
1075         Various functions for printing a message at method entry or exit (for
1076         debugging)
1077         
1078 *****************************************************************************/
1079
1080 s4 methodindent = 0;
1081
1082 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1083                                                                                    methodinfo *m,
1084                                                                                    void *pos,
1085                                                                                    s4 indent)
1086 {
1087         char *logtext;
1088         s4    logtextlen;
1089         s4    dumpsize;
1090
1091         if (opt_verbose || runverbose || opt_verboseexception) {
1092                 /* when running with verbosecall we remove one indent level */
1093
1094                 if (runverbose && indent)
1095                         methodindent--;
1096
1097                 /* calculate message length */
1098
1099                 if (xptr) {
1100                         logtextlen =
1101                                 strlen("Exception ") +
1102                                 utf_strlen(xptr->vftbl->class->name);
1103
1104                 } else {
1105                         logtextlen = strlen("Some Throwable");
1106                 }
1107
1108                 logtextlen += strlen(" thrown in ");
1109
1110                 if (m) {
1111                         logtextlen +=
1112                                 utf_strlen(m->class->name) +
1113                                 strlen(".") +
1114                                 utf_strlen(m->name) +
1115                                 utf_strlen(m->descriptor) +
1116                                 strlen("(NOSYNC,NATIVE");
1117
1118 #if SIZEOF_VOID_P == 8
1119                         logtextlen +=
1120                                 strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1121 #else
1122                         logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1123 #endif
1124
1125                         if (m->class->sourcefile == NULL)
1126                                 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1127                         else
1128                                 logtextlen += utf_strlen(m->class->sourcefile);
1129
1130                         logtextlen += strlen(":65536)");
1131
1132                 } else
1133                         logtextlen += strlen("call_java_method");
1134
1135                 logtextlen += strlen("0");
1136
1137                 /* allocate memory */
1138
1139                 dumpsize = dump_size();
1140
1141                 logtext = DMNEW(char, logtextlen);
1142
1143                 if (xptr) {
1144                         strcpy(logtext, "Exception ");
1145                         utf_strcat_classname(logtext, xptr->vftbl->class->name);
1146
1147                 } else {
1148                         strcpy(logtext, "Some Throwable");
1149                 }
1150
1151                 strcat(logtext, " thrown in ");
1152
1153                 if (m) {
1154                         utf_strcat_classname(logtext, m->class->name);
1155                         strcat(logtext, ".");
1156                         utf_strcat(logtext, m->name);
1157                         utf_strcat(logtext, m->descriptor);
1158
1159                         if (m->flags & ACC_SYNCHRONIZED)
1160                                 strcat(logtext, "(SYNC");
1161                         else
1162                                 strcat(logtext, "(NOSYNC");
1163
1164                         if (m->flags & ACC_NATIVE) {
1165                                 strcat(logtext, ",NATIVE");
1166
1167 #if SIZEOF_VOID_P == 8
1168                                 sprintf(logtext + strlen(logtext),
1169                                                 ")(0x%016lx) at position 0x%016lx",
1170                                                 (ptrint) m->entrypoint, (ptrint) pos);
1171 #else
1172                                 sprintf(logtext + strlen(logtext),
1173                                                 ")(0x%08x) at position 0x%08x",
1174                                                 (ptrint) m->entrypoint, (ptrint) pos);
1175 #endif
1176
1177                         } else {
1178 #if SIZEOF_VOID_P == 8
1179                                 sprintf(logtext + strlen(logtext),
1180                                                 ")(0x%016lx) at position 0x%016lx (",
1181                                                 (ptrint) m->entrypoint, (ptrint) pos);
1182 #else
1183                                 sprintf(logtext + strlen(logtext),
1184                                                 ")(0x%08x) at position 0x%08x (",
1185                                                 (ptrint) m->entrypoint, (ptrint) pos);
1186 #endif
1187
1188                                 if (m->class->sourcefile == NULL)
1189                                         strcat(logtext, "<NO CLASSFILE INFORMATION>");
1190                                 else
1191                                         utf_strcat(logtext, m->class->sourcefile);
1192
1193                                 sprintf(logtext + strlen(logtext), ":%d)", 0);
1194                         }
1195
1196                 } else
1197                         strcat(logtext, "call_java_method");
1198
1199                 log_text(logtext);
1200
1201                 /* release memory */
1202
1203                 dump_release(dumpsize);
1204
1205                 /* print stacktrace for exception */
1206
1207                 if (opt_verboseexception) {
1208                         java_lang_Throwable   *t;
1209                         java_lang_VMThrowable *vmt;
1210                         java_lang_Throwable   *cause;
1211                         utf                   *u;
1212                         stackTraceBuffer      *stb;
1213
1214                         t = (java_lang_Throwable *) xptr;
1215                         cause = t->cause;
1216
1217                         /* print the root exception */
1218
1219                         utf_display_classname(t->header.vftbl->class->name);
1220
1221                         if (t->detailMessage) {
1222                                 u = javastring_toutf(t->detailMessage, false);
1223
1224                                 printf(": ");
1225                                 utf_display(u);
1226                         }
1227
1228                         putc('\n', stdout);
1229
1230                         /* print the cause if available */
1231
1232                         if (cause && (cause != t)) {
1233                                 printf("Caused by: ");
1234                                 utf_display_classname(cause->header.vftbl->class->name);
1235
1236                                 if (cause->detailMessage) {
1237                                         u = javastring_toutf(cause->detailMessage, false);
1238
1239                                         printf(": ");
1240                                         utf_display(u);
1241                                 }
1242
1243                                 putc('\n', stdout);
1244                         }
1245
1246                         /* now print the stacktrace */
1247
1248                         vmt = t->vmState;
1249                         stb = (stackTraceBuffer *) vmt->vmData;
1250
1251                         stacktrace_print_trace(stb);
1252                 }
1253         }
1254
1255         return xptr;
1256 }
1257
1258
1259 /* builtin_trace_args **********************************************************
1260
1261    XXX
1262
1263 *******************************************************************************/
1264
1265 #ifdef TRACE_ARGS_NUM
1266 void builtin_trace_args(s8 a0, s8 a1,
1267 #if TRACE_ARGS_NUM >= 4
1268                                                 s8 a2, s8 a3,
1269 #endif /* TRACE_ARGS_NUM >= 4 */
1270 #if TRACE_ARGS_NUM >= 6
1271                                                 s8 a4, s8 a5,
1272 #endif /* TRACE_ARGS_NUM >= 6 */
1273 #if TRACE_ARGS_NUM == 8
1274                                                 s8 a6, s8 a7,
1275 #endif /* TRACE_ARGS_NUM == 8 */
1276                                                 methodinfo *m)
1277 {
1278         methoddesc *md;
1279         char       *logtext;
1280         s4          logtextlen;
1281         s4          dumpsize;
1282         s4          i;
1283         s4          pos;
1284
1285         md = m->parseddesc;
1286
1287         /* calculate message length */
1288
1289         logtextlen =
1290                 6 + methodindent + strlen("called: ") +
1291                 utf_strlen(m->class->name) +
1292                 strlen(".") +
1293                 utf_strlen(m->name) +
1294                 utf_strlen(m->descriptor) +
1295                 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1296
1297         /* add maximal argument length */
1298
1299         logtextlen += strlen("0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, ...(255)");
1300
1301         /* allocate memory */
1302
1303         dumpsize = dump_size();
1304
1305         logtext = DMNEW(char, logtextlen);
1306
1307         sprintf(logtext,"-%d-",methodindent);
1308         pos = strlen(logtext);
1309
1310         for (i = 0; i < methodindent; i++)
1311                 logtext[pos++] = '\t';
1312
1313         strcpy(logtext + pos, "called: ");
1314
1315         utf_strcat_classname(logtext, m->class->name);
1316         strcat(logtext, ".");
1317         utf_strcat(logtext, m->name);
1318         utf_strcat(logtext, m->descriptor);
1319
1320         if (m->flags & ACC_PUBLIC)       strcat(logtext, " PUBLIC");
1321         if (m->flags & ACC_PRIVATE)      strcat(logtext, " PRIVATE");
1322         if (m->flags & ACC_PROTECTED)    strcat(logtext, " PROTECTED");
1323         if (m->flags & ACC_STATIC)       strcat(logtext, " STATIC");
1324         if (m->flags & ACC_FINAL)        strcat(logtext, " FINAL");
1325         if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1326         if (m->flags & ACC_VOLATILE)     strcat(logtext, " VOLATILE");
1327         if (m->flags & ACC_TRANSIENT)    strcat(logtext, " TRANSIENT");
1328         if (m->flags & ACC_NATIVE)       strcat(logtext, " NATIVE");
1329         if (m->flags & ACC_INTERFACE)    strcat(logtext, " INTERFACE");
1330         if (m->flags & ACC_ABSTRACT)     strcat(logtext, " ABSTRACT");
1331
1332         strcat(logtext, "(");
1333
1334         /* xxxprintf ?Bug? an PowerPc Linux (rlwinm.inso)                */
1335         /* Only Arguments in integer Registers are passed correctly here */
1336         /* long longs spilled on Stack have an wrong offset of +4        */
1337         /* So preliminary Bugfix: Only pass 3 params at once to sprintf  */
1338         /* for SIZEOG_VOID_P == 4 && TRACE_ARGS_NUM == 8                 */
1339         switch (md->paramcount) {
1340         case 0:
1341                 break;
1342
1343 #if SIZEOF_VOID_P == 4
1344         case 1:
1345                 sprintf(logtext + strlen(logtext),
1346                                 "0x%llx",
1347                                 a0);
1348                 break;
1349
1350         case 2:
1351                 sprintf(logtext + strlen(logtext),
1352                                 "0x%llx, 0x%llx",
1353                                 a0, a1);
1354                 break;
1355
1356 #if TRACE_ARGS_NUM >= 4
1357         case 3:
1358                 sprintf(logtext + strlen(logtext),
1359                                 "0x%llx, 0x%llx, 0x%llx",
1360                                 a0, a1, a2);
1361                 break;
1362
1363         case 4:
1364                 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1365                                 , a0, a1, a2);
1366                 sprintf(logtext + strlen(logtext), ", 0x%llx", a3);
1367
1368                 break;
1369 #endif /* TRACE_ARGS_NUM >= 4 */
1370
1371 #if TRACE_ARGS_NUM >= 6
1372         case 5:
1373                 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1374                                 , a0, a1, a2);
1375                 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a3, a4);
1376                 break;
1377
1378
1379         case 6:
1380                 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1381                                 , a0, a1, a2);
1382                 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1383                                 , a3, a4, a5);
1384                 break;
1385 #endif /* TRACE_ARGS_NUM >= 6 */
1386
1387 #if TRACE_ARGS_NUM == 8
1388         case 7:
1389                 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1390                                 , a0, a1, a2);
1391                 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1392                                 , a3, a4, a5);
1393                 sprintf(logtext + strlen(logtext), ", 0x%llx", a6);
1394                 break;
1395
1396         case 8:
1397                 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1398                                 , a0, a1, a2);
1399                 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1400                                 , a3, a4, a5);
1401                 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a6, a7);
1402                 break;
1403 #endif /* TRACE_ARGS_NUM == 8 */
1404
1405         default:
1406 #if TRACE_ARGS_NUM == 2
1407                 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, ...(%d)", a0, a1, md->paramcount - 2);
1408
1409 #elif TRACE_ARGS_NUM == 4
1410                 sprintf(logtext + strlen(logtext),
1411                                 "0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1412                                 a0, a1, a2, a3, md->paramcount - 4);
1413
1414 #elif TRACE_ARGS_NUM == 6
1415                 sprintf(logtext + strlen(logtext),
1416                                 "0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1417                                 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1418
1419 #elif TRACE_ARGS_NUM == 8
1420                 sprintf(logtext + strlen(logtext),"0x%llx, 0x%llx, 0x%llx,"
1421                                 , a0, a1, a2);
1422                 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, 0x%llx,"
1423                                 , a3, a4, a5);
1424                 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, ...(%d)"
1425                                 , a6, a7, md->paramcount - 8);
1426 #endif
1427                 break;
1428
1429 #else /* SIZEOF_VOID_P == 4 */
1430
1431         case 1:
1432                 sprintf(logtext + strlen(logtext),
1433                                 "0x%lx",
1434                                 a0);
1435                 break;
1436
1437         case 2:
1438                 sprintf(logtext + strlen(logtext),
1439                                 "0x%lx, 0x%lx",
1440                                 a0, a1);
1441                 break;
1442
1443         case 3:
1444                 sprintf(logtext + strlen(logtext),
1445                                 "0x%lx, 0x%lx, 0x%lx", a0, a1, a2);
1446                 break;
1447
1448         case 4:
1449                 sprintf(logtext + strlen(logtext),
1450                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx",
1451                                 a0, a1, a2, a3);
1452                 break;
1453
1454 #if TRACE_ARGS_NUM >= 6
1455         case 5:
1456                 sprintf(logtext + strlen(logtext),
1457                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1458                                 a0, a1, a2, a3, a4);
1459                 break;
1460
1461         case 6:
1462                 sprintf(logtext + strlen(logtext),
1463                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1464                                 a0, a1, a2, a3, a4, a5);
1465                 break;
1466 #endif /* TRACE_ARGS_NUM >= 6 */
1467
1468 #if TRACE_ARGS_NUM == 8
1469         case 7:
1470                 sprintf(logtext + strlen(logtext),
1471                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1472                                 a0, a1, a2, a3, a4, a5, a6);
1473                 break;
1474
1475         case 8:
1476                 sprintf(logtext + strlen(logtext),
1477                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1478                                 a0, a1, a2, a3, a4, a5, a6, a7);
1479                 break;
1480 #endif /* TRACE_ARGS_NUM == 8 */
1481
1482         default:
1483 #if TRACE_ARGS_NUM == 4
1484                 sprintf(logtext + strlen(logtext),
1485                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1486                                 a0, a1, a2, a3, md->paramcount - 4);
1487
1488 #elif TRACE_ARGS_NUM == 6
1489                 sprintf(logtext + strlen(logtext),
1490                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1491                                 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1492
1493 #elif TRACE_ARGS_NUM == 8
1494                 sprintf(logtext + strlen(logtext),
1495                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1496                                 a0, a1, a2, a3, a4, a5, a6, a7, md->paramcount - 8);
1497 #endif
1498                 break;
1499 #endif /* SIZEOF_VOID_P == 4 */
1500         }
1501
1502         strcat(logtext, ")");
1503
1504         log_text(logtext);
1505
1506         /* release memory */
1507
1508         dump_release(dumpsize);
1509
1510         methodindent++;
1511 }
1512 #endif
1513
1514
1515 /* builtin_displaymethodstop ***************************************************
1516
1517    XXX
1518
1519 *******************************************************************************/
1520
1521 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1522 {
1523         methoddesc *md;
1524         char       *logtext;
1525         s4          logtextlen;
1526         s4          dumpsize;
1527         s4          i;
1528         s4          pos;
1529         imm_union   imu;
1530
1531         md = m->parseddesc;
1532
1533         /* calculate message length */
1534
1535         logtextlen =
1536                 6 + methodindent + strlen("finished: ") +
1537                 utf_strlen(m->class->name) +
1538                 strlen(".") +
1539                 utf_strlen(m->name) +
1540                 utf_strlen(m->descriptor) +
1541                 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1542
1543         /* add maximal argument length */
1544
1545         logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1546
1547         /* allocate memory */
1548
1549         dumpsize = dump_size();
1550
1551         logtext = DMNEW(char, logtextlen);
1552
1553         /* outdent the log message */
1554
1555         if (methodindent)
1556                 methodindent--;
1557         else
1558                 log_text("WARNING: unmatched methodindent--");
1559
1560         /* generate the message */
1561
1562         sprintf(logtext,"-%d-",methodindent);
1563         pos = strlen(logtext);
1564
1565         for (i = 0; i < methodindent; i++)
1566                 logtext[pos++] = '\t';
1567
1568         strcpy(logtext + pos, "finished: ");
1569         utf_strcat_classname(logtext, m->class->name);
1570         strcat(logtext, ".");
1571         utf_strcat(logtext, m->name);
1572         utf_strcat(logtext, m->descriptor);
1573
1574         switch (md->returntype.type) {
1575         case TYPE_INT:
1576                 sprintf(logtext + strlen(logtext), "->%d (0x%08x)", (s4) l, (s4) l);
1577                 break;
1578
1579         case TYPE_LNG:
1580 #if SIZEOF_VOID_P == 4
1581                 sprintf(logtext + strlen(logtext), "->%lld (0x%016llx)", (s8) l, l);
1582 #else
1583                 sprintf(logtext + strlen(logtext), "->%ld (0x%016lx)", (s8) l, l);
1584 #endif
1585                 break;
1586
1587         case TYPE_ADR:
1588                 sprintf(logtext + strlen(logtext), "->%p", (void *) (ptrint) l);
1589                 break;
1590
1591         case TYPE_FLT:
1592                 imu.f = f;
1593                 sprintf(logtext + strlen(logtext), "->%.8f (0x%08x)", f, imu.i);
1594                 break;
1595
1596         case TYPE_DBL:
1597                 imu.d = d;
1598 #if SIZEOF_VOID_P == 4
1599                 sprintf(logtext + strlen(logtext), "->%.16g (0x%016llx)", d, imu.l);
1600 #else
1601                 sprintf(logtext + strlen(logtext), "->%.16g (0x%016lx)", d, imu.l);
1602 #endif
1603                 break;
1604         }
1605
1606         log_text(logtext);
1607
1608         /* release memory */
1609
1610         dump_release(dumpsize);
1611 }
1612
1613
1614 /****************************************************************************
1615                          SYNCHRONIZATION FUNCTIONS
1616 *****************************************************************************/
1617
1618 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1619 /*
1620  * Lock the mutex of an object.
1621  */
1622 void internal_lock_mutex_for_object(java_objectheader *object)
1623 {
1624         mutexHashEntry *entry;
1625         int hashValue;
1626
1627         assert(object != 0);
1628
1629         hashValue = MUTEX_HASH_VALUE(object);
1630         entry = &mutexHashTable[hashValue];
1631
1632         if (entry->object != 0) {
1633                 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1634                         entry->object = 0;
1635                         entry->mutex.holder = 0;
1636                         entry->mutex.count = 0;
1637                         entry->mutex.muxWaiters = 0;
1638
1639                 } else {
1640                         while (entry->next != 0 && entry->object != object)
1641                                 entry = entry->next;
1642
1643                         if (entry->object != object) {
1644                                 entry->next = firstFreeOverflowEntry;
1645                                 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1646
1647                                 entry = entry->next;
1648                                 entry->object = 0;
1649                                 entry->next = 0;
1650                                 assert(entry->conditionCount == 0);
1651                         }
1652                 }
1653
1654         } else {
1655                 entry->mutex.holder = 0;
1656                 entry->mutex.count = 0;
1657                 entry->mutex.muxWaiters = 0;
1658         }
1659
1660         if (entry->object == 0)
1661                 entry->object = object;
1662         
1663         internal_lock_mutex(&entry->mutex);
1664 }
1665 #endif
1666
1667
1668 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1669 /*
1670  * Unlocks the mutex of an object.
1671  */
1672 void internal_unlock_mutex_for_object (java_objectheader *object)
1673 {
1674         int hashValue;
1675         mutexHashEntry *entry;
1676
1677         hashValue = MUTEX_HASH_VALUE(object);
1678         entry = &mutexHashTable[hashValue];
1679
1680         if (entry->object == object) {
1681                 internal_unlock_mutex(&entry->mutex);
1682
1683         } else {
1684                 while (entry->next != 0 && entry->next->object != object)
1685                         entry = entry->next;
1686
1687                 assert(entry->next != 0);
1688
1689                 internal_unlock_mutex(&entry->next->mutex);
1690
1691                 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1692                         mutexHashEntry *unlinked = entry->next;
1693
1694                         entry->next = unlinked->next;
1695                         unlinked->next = firstFreeOverflowEntry;
1696                         firstFreeOverflowEntry = unlinked;
1697                 }
1698         }
1699 }
1700 #endif
1701
1702
1703 #if defined(USE_THREADS)
1704 void builtin_monitorenter(java_objectheader *o)
1705 {
1706 #if !defined(NATIVE_THREADS)
1707         int hashValue;
1708
1709         ++blockInts;
1710
1711         hashValue = MUTEX_HASH_VALUE(o);
1712         if (mutexHashTable[hashValue].object == o 
1713                 && mutexHashTable[hashValue].mutex.holder == currentThread)
1714                 ++mutexHashTable[hashValue].mutex.count;
1715         else
1716                 internal_lock_mutex_for_object(o);
1717
1718         --blockInts;
1719 #else
1720         monitorEnter((threadobject *) THREADOBJECT, o);
1721 #endif
1722 }
1723 #endif
1724
1725
1726 #if defined(USE_THREADS)
1727 /*
1728  * Locks the class object - needed for static synchronized methods.
1729  * The use_class_as_object call is needed in order to circumvent a
1730  * possible deadlock with builtin_monitorenter called by another
1731  * thread calling use_class_as_object.
1732  */
1733 void builtin_staticmonitorenter(classinfo *c)
1734 {
1735         use_class_as_object(c);
1736         builtin_monitorenter(&c->header);
1737 }
1738 #endif
1739
1740
1741 #if defined(USE_THREADS)
1742 void builtin_monitorexit(java_objectheader *o)
1743 {
1744 #if !defined(NATIVE_THREADS)
1745         int hashValue;
1746
1747         ++blockInts;
1748
1749         hashValue = MUTEX_HASH_VALUE(o);
1750         if (mutexHashTable[hashValue].object == o) {
1751                 if (mutexHashTable[hashValue].mutex.count == 1
1752                         && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1753                         internal_unlock_mutex_for_object(o);
1754                 else
1755                         --mutexHashTable[hashValue].mutex.count;
1756
1757         } else
1758                 internal_unlock_mutex_for_object(o);
1759
1760         --blockInts;
1761 #else
1762         monitorExit((threadobject *) THREADOBJECT, o);
1763 #endif
1764 }
1765 #endif
1766
1767
1768 /*****************************************************************************
1769                           MISCELLANEOUS HELPER FUNCTIONS
1770 *****************************************************************************/
1771
1772
1773
1774 /*********** Functions for integer divisions *****************************
1775  
1776         On some systems (eg. DEC ALPHA), integer division is not supported by the
1777         CPU. These helper functions implement the missing functionality.
1778
1779 ******************************************************************************/
1780
1781 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1782 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1783
1784
1785 /************** Functions for long arithmetics *******************************
1786
1787         On systems where 64 bit Integers are not supported by the CPU, these
1788         functions are needed.
1789
1790 ******************************************************************************/
1791
1792 s8 builtin_ladd(s8 a, s8 b)
1793 {
1794         s8 c;
1795
1796 #if U8_AVAILABLE
1797         c = a + b; 
1798 #else
1799         c = builtin_i2l(0);
1800 #endif
1801
1802         return c;
1803 }
1804
1805 s8 builtin_lsub(s8 a, s8 b) 
1806 {
1807         s8 c;
1808
1809 #if U8_AVAILABLE
1810         c = a - b; 
1811 #else
1812         c = builtin_i2l(0);
1813 #endif
1814
1815         return c;
1816 }
1817
1818 s8 builtin_lmul(s8 a, s8 b) 
1819 {
1820         s8 c;
1821
1822 #if U8_AVAILABLE
1823         c = a * b; 
1824 #else
1825         c = builtin_i2l(0);
1826 #endif
1827
1828         return c;
1829 }
1830
1831 s8 builtin_ldiv(s8 a, s8 b) 
1832 {
1833         s8 c;
1834
1835 #if U8_AVAILABLE
1836         c = a / b; 
1837 #else
1838         c = builtin_i2l(0);
1839 #endif
1840
1841         return c;
1842 }
1843
1844 s8 builtin_lrem(s8 a, s8 b) 
1845 {
1846         s8 c;
1847
1848 #if U8_AVAILABLE
1849         c = a % b; 
1850 #else
1851         c = builtin_i2l(0);
1852 #endif
1853
1854         return c;
1855 }
1856
1857 s8 builtin_lshl(s8 a, s4 b) 
1858 {
1859         s8 c;
1860
1861 #if U8_AVAILABLE
1862         c = a << (b & 63);
1863 #else
1864         c = builtin_i2l(0);
1865 #endif
1866
1867         return c;
1868 }
1869
1870 s8 builtin_lshr(s8 a, s4 b) 
1871 {
1872         s8 c;
1873
1874 #if U8_AVAILABLE
1875         c = a >> (b & 63);
1876 #else
1877         c = builtin_i2l(0);
1878 #endif
1879
1880         return c;
1881 }
1882
1883 s8 builtin_lushr(s8 a, s4 b) 
1884 {
1885         s8 c;
1886
1887 #if U8_AVAILABLE
1888         c = ((u8) a) >> (b & 63);
1889 #else
1890         c = builtin_i2l(0);
1891 #endif
1892
1893         return c;
1894 }
1895
1896 s8 builtin_land(s8 a, s8 b) 
1897 {
1898         s8 c;
1899
1900 #if U8_AVAILABLE
1901         c = a & b; 
1902 #else
1903         c = builtin_i2l(0);
1904 #endif
1905
1906         return c;
1907 }
1908
1909 s8 builtin_lor(s8 a, s8 b) 
1910 {
1911         s8 c;
1912
1913 #if U8_AVAILABLE
1914         c = a | b; 
1915 #else
1916         c = builtin_i2l(0);
1917 #endif
1918
1919         return c;
1920 }
1921
1922 s8 builtin_lxor(s8 a, s8 b) 
1923 {
1924         s8 c;
1925
1926 #if U8_AVAILABLE
1927         c = a ^ b; 
1928 #else
1929         c = builtin_i2l(0);
1930 #endif
1931
1932         return c;
1933 }
1934
1935 s8 builtin_lneg(s8 a) 
1936 {
1937         s8 c;
1938
1939 #if U8_AVAILABLE
1940         c = -a;
1941 #else
1942         c = builtin_i2l(0);
1943 #endif
1944
1945         return c;
1946 }
1947
1948 s4 builtin_lcmp(s8 a, s8 b) 
1949
1950 #if U8_AVAILABLE
1951         if (a < b) return -1;
1952         if (a > b) return 1;
1953         return 0;
1954 #else
1955         return 0;
1956 #endif
1957 }
1958
1959
1960
1961
1962
1963 /*********** Functions for floating point operations *************************/
1964
1965 /* used to convert FLT_xxx defines into float values */
1966
1967 static inline float intBitsToFloat(s4 i)
1968 {
1969         imm_union imb;
1970
1971         imb.i = i;
1972         return imb.f;
1973 }
1974
1975
1976 /* used to convert DBL_xxx defines into double values */
1977
1978 static inline float longBitsToDouble(s8 l)
1979 {
1980         imm_union imb;
1981
1982         imb.l = l;
1983         return imb.d;
1984 }
1985
1986
1987 float builtin_fadd(float a, float b)
1988 {
1989         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1990         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1991         if (finitef(a)) {
1992                 if (finitef(b))
1993                         return a + b;
1994                 else
1995                         return b;
1996         }
1997         else {
1998                 if (finitef(b))
1999                         return a;
2000                 else {
2001                         if (copysignf(1.0, a) == copysignf(1.0, b))
2002                                 return a;
2003                         else
2004                                 return intBitsToFloat(FLT_NAN);
2005                 }
2006         }
2007 }
2008
2009
2010 float builtin_fsub(float a, float b)
2011 {
2012         return builtin_fadd(a, builtin_fneg(b));
2013 }
2014
2015
2016 float builtin_fmul(float a, float b)
2017 {
2018         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2019         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2020         if (finitef(a)) {
2021                 if (finitef(b)) return a * b;
2022                 else {
2023                         if (a == 0) return intBitsToFloat(FLT_NAN);
2024                         else return copysignf(b, copysignf(1.0, b)*a);
2025                 }
2026         }
2027         else {
2028                 if (finitef(b)) {
2029                         if (b == 0) return intBitsToFloat(FLT_NAN);
2030                         else return copysignf(a, copysignf(1.0, a)*b);
2031                 }
2032                 else {
2033                         return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2034                 }
2035         }
2036 }
2037
2038
2039 /* builtin_ddiv ****************************************************************
2040
2041    Implementation as described in VM Spec.
2042
2043 *******************************************************************************/
2044
2045 float builtin_fdiv(float a, float b)
2046 {
2047         if (finitef(a)) {
2048                 if (finitef(b)) {
2049                         /* If neither value1' nor value2' is NaN, the sign of the result */
2050                         /* is positive if both values have the same sign, negative if the */
2051                         /* values have different signs. */
2052
2053                         return a / b;
2054
2055                 } else {
2056                         if (isnanf(b)) {
2057                                 /* If either value1' or value2' is NaN, the result is NaN. */
2058
2059                                 return intBitsToFloat(FLT_NAN);
2060
2061                         } else {
2062                                 /* Division of a finite value by an infinity results in a */
2063                                 /* signed zero, with the sign-producing rule just given. */
2064
2065                                 /* is sign equal? */
2066
2067                                 if (copysignf(1.0, a) == copysignf(1.0, b))
2068                                         return 0.0;
2069                                 else
2070                                         return -0.0;
2071                         }
2072                 }
2073
2074         } else {
2075                 if (isnanf(a)) {
2076                         /* If either value1' or value2' is NaN, the result is NaN. */
2077
2078                         return intBitsToFloat(FLT_NAN);
2079
2080                 } else if (finitef(b)) {
2081                         /* Division of an infinity by a finite value results in a signed */
2082                         /* infinity, with the sign-producing rule just given. */
2083
2084                         /* is sign equal? */
2085
2086                         if (copysignf(1.0, a) == copysignf(1.0, b))
2087                                 return intBitsToFloat(FLT_POSINF);
2088                         else
2089                                 return intBitsToFloat(FLT_NEGINF);
2090
2091                 } else {
2092                         /* Division of an infinity by an infinity results in NaN. */
2093
2094                         return intBitsToFloat(FLT_NAN);
2095                 }
2096         }
2097 }
2098
2099
2100 float builtin_frem(float a, float b)
2101 {
2102         return fmodf(a, b);
2103 }
2104
2105
2106 float builtin_fneg(float a)
2107 {
2108         if (isnanf(a)) return a;
2109         else {
2110                 if (finitef(a)) return -a;
2111                 else return copysignf(a, -copysignf(1.0, a));
2112         }
2113 }
2114
2115
2116 s4 builtin_fcmpl(float a, float b)
2117 {
2118         if (isnanf(a)) return -1;
2119         if (isnanf(b)) return -1;
2120         if (!finitef(a) || !finitef(b)) {
2121                 a = finitef(a) ? 0 : copysignf(1.0,     a);
2122                 b = finitef(b) ? 0 : copysignf(1.0, b);
2123         }
2124         if (a > b) return 1;
2125         if (a == b) return 0;
2126         return -1;
2127 }
2128
2129
2130 s4 builtin_fcmpg(float a, float b)
2131 {
2132         if (isnanf(a)) return 1;
2133         if (isnanf(b)) return 1;
2134         if (!finitef(a) || !finitef(b)) {
2135                 a = finitef(a) ? 0 : copysignf(1.0, a);
2136                 b = finitef(b) ? 0 : copysignf(1.0, b);
2137         }
2138         if (a > b) return 1;
2139         if (a == b) return 0;
2140         return -1;
2141 }
2142
2143
2144
2145 /************************* Functions for doubles ****************************/
2146
2147 double builtin_dadd(double a, double b)
2148 {
2149         if (isnan(a)) return longBitsToDouble(DBL_NAN);
2150         if (isnan(b)) return longBitsToDouble(DBL_NAN);
2151         if (finite(a)) {
2152                 if (finite(b)) return a + b;
2153                 else return b;
2154         }
2155         else {
2156                 if (finite(b)) return a;
2157                 else {
2158                         if (copysign(1.0, a)==copysign(1.0, b)) return a;
2159                         else return longBitsToDouble(DBL_NAN);
2160                 }
2161         }
2162 }
2163
2164
2165 double builtin_dsub(double a, double b)
2166 {
2167         return builtin_dadd(a, builtin_dneg(b));
2168 }
2169
2170
2171 double builtin_dmul(double a, double b)
2172 {
2173         if (isnan(a)) return longBitsToDouble(DBL_NAN);
2174         if (isnan(b)) return longBitsToDouble(DBL_NAN);
2175         if (finite(a)) {
2176                 if (finite(b)) return a * b;
2177                 else {
2178                         if (a == 0) return longBitsToDouble(DBL_NAN);
2179                         else return copysign(b, copysign(1.0, b) * a);
2180                 }
2181         }
2182         else {
2183                 if (finite(b)) {
2184                         if (b == 0) return longBitsToDouble(DBL_NAN);
2185                         else return copysign(a, copysign(1.0, a) * b);
2186                 }
2187                 else {
2188                         return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2189                 }
2190         }
2191 }
2192
2193
2194 /* builtin_ddiv ****************************************************************
2195
2196    Implementation as described in VM Spec.
2197
2198 *******************************************************************************/
2199
2200 double builtin_ddiv(double a, double b)
2201 {
2202         if (finite(a)) {
2203                 if (finite(b)) {
2204                         /* If neither value1' nor value2' is NaN, the sign of the result */
2205                         /* is positive if both values have the same sign, negative if the */
2206                         /* values have different signs. */
2207
2208                         return a / b;
2209
2210                 } else {
2211                         if (isnan(b)) {
2212                                 /* If either value1' or value2' is NaN, the result is NaN. */
2213
2214                                 return longBitsToDouble(DBL_NAN);
2215
2216                         } else {
2217                                 /* Division of a finite value by an infinity results in a */
2218                                 /* signed zero, with the sign-producing rule just given. */
2219
2220                                 /* is sign equal? */
2221
2222                                 if (copysign(1.0, a) == copysign(1.0, b))
2223                                         return 0.0;
2224                                 else
2225                                         return -0.0;
2226                         }
2227                 }
2228
2229         } else {
2230                 if (isnan(a)) {
2231                         /* If either value1' or value2' is NaN, the result is NaN. */
2232
2233                         return longBitsToDouble(DBL_NAN);
2234
2235                 } else if (finite(b)) {
2236                         /* Division of an infinity by a finite value results in a signed */
2237                         /* infinity, with the sign-producing rule just given. */
2238
2239                         /* is sign equal? */
2240
2241                         if (copysign(1.0, a) == copysign(1.0, b))
2242                                 return longBitsToDouble(DBL_POSINF);
2243                         else
2244                                 return longBitsToDouble(DBL_NEGINF);
2245
2246                 } else {
2247                         /* Division of an infinity by an infinity results in NaN. */
2248
2249                         return longBitsToDouble(DBL_NAN);
2250                 }
2251         }
2252 }
2253
2254
2255 double builtin_drem(double a, double b)
2256 {
2257         return fmod(a, b);
2258 }
2259
2260 /* builtin_dneg ****************************************************************
2261
2262    Implemented as described in VM Spec.
2263
2264 *******************************************************************************/
2265
2266 double builtin_dneg(double a)
2267 {
2268         if (isnan(a)) {
2269                 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2270                 /* sign). */
2271
2272                 return a;
2273
2274         } else {
2275                 if (finite(a)) {
2276                         /* If the operand is a zero, the result is the zero of opposite */
2277                         /* sign. */
2278
2279                         return -a;
2280
2281                 } else {
2282                         /* If the operand is an infinity, the result is the infinity of */
2283                         /* opposite sign. */
2284
2285                         return copysign(a, -copysign(1.0, a));
2286                 }
2287         }
2288 }
2289
2290
2291 s4 builtin_dcmpl(double a, double b)
2292 {
2293         if (isnan(a)) return -1;
2294         if (isnan(b)) return -1;
2295         if (!finite(a) || !finite(b)) {
2296                 a = finite(a) ? 0 : copysign(1.0, a);
2297                 b = finite(b) ? 0 : copysign(1.0, b);
2298         }
2299         if (a > b) return 1;
2300         if (a == b) return 0;
2301         return -1;
2302 }
2303
2304
2305 s4 builtin_dcmpg(double a, double b)
2306 {
2307         if (isnan(a)) return 1;
2308         if (isnan(b)) return 1;
2309         if (!finite(a) || !finite(b)) {
2310                 a = finite(a) ? 0 : copysign(1.0, a);
2311                 b = finite(b) ? 0 : copysign(1.0, b);
2312         }
2313         if (a > b) return 1;
2314         if (a == b) return 0;
2315         return -1;
2316 }
2317
2318
2319 /*********************** Conversion operations ****************************/
2320
2321 s8 builtin_i2l(s4 i)
2322 {
2323 #if U8_AVAILABLE
2324         return i;
2325 #else
2326         s8 v;
2327         v.high = 0;
2328         v.low = i;
2329         return v;
2330 #endif
2331 }
2332
2333
2334 float builtin_i2f(s4 a)
2335 {
2336         float f = (float) a;
2337         return f;
2338 }
2339
2340
2341 double builtin_i2d(s4 a)
2342 {
2343         double d = (double) a;
2344         return d;
2345 }
2346
2347
2348 s4 builtin_l2i(s8 l)
2349 {
2350 #if U8_AVAILABLE
2351         return (s4) l;
2352 #else
2353         return l.low;
2354 #endif
2355 }
2356
2357
2358 float builtin_l2f(s8 a)
2359 {
2360 #if U8_AVAILABLE
2361         float f = (float) a;
2362         return f;
2363 #else
2364         return 0.0;
2365 #endif
2366 }
2367
2368
2369 double builtin_l2d(s8 a)
2370 {
2371 #if U8_AVAILABLE
2372         double d = (double) a;
2373         return d;
2374 #else
2375         return 0.0;
2376 #endif
2377 }
2378
2379
2380 s4 builtin_f2i(float a) 
2381 {
2382         s4 i;
2383
2384         i = builtin_d2i((double) a);
2385
2386         return i;
2387
2388         /*      float f;
2389         
2390                 if (isnanf(a))
2391                 return 0;
2392                 if (finitef(a)) {
2393                 if (a > 2147483647)
2394                 return 2147483647;
2395                 if (a < (-2147483648))
2396                 return (-2147483648);
2397                 return (s4) a;
2398                 }
2399                 f = copysignf((float) 1.0, a);
2400                 if (f > 0)
2401                 return 2147483647;
2402                 return (-2147483648); */
2403 }
2404
2405
2406 s8 builtin_f2l(float a)
2407 {
2408         s8 l;
2409
2410         l = builtin_d2l((double) a);
2411
2412         return l;
2413
2414         /*      float f;
2415         
2416                 if (finitef(a)) {
2417                 if (a > 9223372036854775807L)
2418                 return 9223372036854775807L;
2419                 if (a < (-9223372036854775808L))
2420                 return (-9223372036854775808L);
2421                 return (s8) a;
2422                 }
2423                 if (isnanf(a))
2424                 return 0;
2425                 f = copysignf((float) 1.0, a);
2426                 if (f > 0)
2427                 return 9223372036854775807L;
2428                 return (-9223372036854775808L); */
2429 }
2430
2431
2432 double builtin_f2d(float a)
2433 {
2434         if (finitef(a)) return (double) a;
2435         else {
2436                 if (isnanf(a))
2437                         return longBitsToDouble(DBL_NAN);
2438                 else
2439                         return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2440         }
2441 }
2442
2443
2444 s4 builtin_d2i(double a) 
2445
2446         double d;
2447         
2448         if (finite(a)) {
2449                 if (a >= 2147483647)
2450                         return 2147483647;
2451                 if (a <= (-2147483647-1))
2452                         return (-2147483647-1);
2453                 return (s4) a;
2454         }
2455         if (isnan(a))
2456                 return 0;
2457         d = copysign(1.0, a);
2458         if (d > 0)
2459                 return 2147483647;
2460         return (-2147483647-1);
2461 }
2462
2463
2464 s8 builtin_d2l(double a)
2465 {
2466         double d;
2467         
2468         if (finite(a)) {
2469                 if (a >= 9223372036854775807LL)
2470                         return 9223372036854775807LL;
2471                 if (a <= (-9223372036854775807LL-1))
2472                         return (-9223372036854775807LL-1);
2473                 return (s8) a;
2474         }
2475         if (isnan(a))
2476                 return 0;
2477         d = copysign(1.0, a);
2478         if (d > 0)
2479                 return 9223372036854775807LL;
2480         return (-9223372036854775807LL-1);
2481 }
2482
2483
2484 float builtin_d2f(double a)
2485 {
2486         if (finite(a))
2487                 return (float) a;
2488         else {
2489                 if (isnan(a))
2490                         return intBitsToFloat(FLT_NAN);
2491                 else
2492                         return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2493         }
2494 }
2495
2496
2497 /* builtin_clone_array *********************************************************
2498
2499    Wrapper function for cloning arrays.
2500
2501 *******************************************************************************/
2502
2503 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
2504 {
2505         java_arrayheader    *ah;
2506         java_lang_Cloneable *c;
2507
2508         c = (java_lang_Cloneable *) o;
2509
2510         ah = (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, c);
2511
2512         return ah;
2513 }
2514
2515
2516 /* builtin_asm_get_exceptionptrptr *********************************************
2517
2518    this is a wrapper for calls from asmpart
2519
2520 *******************************************************************************/
2521
2522 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2523 java_objectheader **builtin_asm_get_exceptionptrptr(void)
2524 {
2525         return builtin_get_exceptionptrptr();
2526 }
2527 #endif
2528
2529
2530 /*
2531  * These are local overrides for various environment variables in Emacs.
2532  * Please do not remove this and leave it at the end of the file, where
2533  * Emacs will automagically detect them.
2534  * ---------------------------------------------------------------------
2535  * Local variables:
2536  * mode: c
2537  * indent-tabs-mode: t
2538  * c-basic-offset: 4
2539  * tab-width: 4
2540  * End:
2541  */