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