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