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