POWERPC defines in builtin_trace_args and builtin_displaymethodstop.
[cacao.git] / src / vm / builtin.c
1 /* builtin.c - functions for unsupported operations
2
3    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4    R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5    M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6    P. Tomsich, J. Wenninger
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    Contains C functions for JavaVM Instructions that cannot be
32    translated to machine language directly. Consequently, the
33    generated machine code for these instructions contains function
34    calls instead of machine instructions, using the C calling
35    convention.
36
37    $Id: builtin.c 957 2004-03-14 21:01:12Z twisti $
38
39 */
40
41
42 #include <assert.h>
43 #include <string.h>
44 #include <math.h>
45 #include "main.h"
46 #include "global.h"
47 #include "builtin.h"
48 #include "native.h"
49 #include "loader.h"
50 #include "tables.h"
51 #include "asmpart.h"
52 #include "mm/boehm.h"
53 #include "threads/thread.h"
54 #include "threads/locks.h"
55 #include "toolbox/loging.h"
56 #include "toolbox/memory.h"
57 #include "nat/java_lang_Cloneable.h"
58 #include "nat/java_lang_VMObject.h"
59
60
61 #undef DEBUG /*define DEBUG 1*/
62
63
64 THREADSPECIFIC methodinfo* _threadrootmethod = NULL;
65 THREADSPECIFIC void *_thread_nativestackframeinfo=NULL;
66
67 /*****************************************************************************
68                                                                 TYPE CHECKS
69 *****************************************************************************/
70
71
72
73 /*************** internal function: builtin_isanysubclass *********************
74
75         Checks a subclass relation between two classes. Implemented interfaces
76         are interpreted as super classes.
77         Return value:  1 ... sub is subclass of super
78                                    0 ... otherwise
79                                         
80 *****************************************************************************/                                  
81 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
82
83         s4 res;
84
85         /*classinfo *tmp;*/
86         if (super->flags & ACC_INTERFACE)
87                 return (sub->vftbl->interfacetablelength > super->index) &&
88                         (sub->vftbl->interfacetable[-super->index] != NULL);
89
90         /*
91           while (sub != 0)
92           if (sub == super)
93           return 1;
94           else
95           sub = sub->super;
96
97           return 0;
98         */
99
100 /*
101         for (tmp=sub;tmp!=0;tmp=tmp->super) {
102                 printf("->");
103                 utf_display(tmp->name);
104         }
105                 printf("\n\n");
106         
107         for (tmp=super;tmp!=0;tmp=tmp->super) {
108                 printf("->");
109                 utf_display(tmp->name);
110         }
111                 printf("\n");
112         
113
114         printf("sub->vftbl->baseval %d, super->vftbl->baseval %d\n diff %d, super->vftbl->diffval %d\n",
115                         sub->vftbl->baseval, super->vftbl->baseval, (unsigned)(sub->vftbl->baseval - super->vftbl->baseval),
116                         super->vftbl->diffval); */
117
118 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
119         cast_lock();
120 #endif
121
122         res = (unsigned) (sub->vftbl->baseval - super->vftbl->baseval) <=
123                 (unsigned) (super->vftbl->diffval);
124
125 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
126         cast_unlock();
127 #endif
128
129         return res;
130 }
131
132 s4 builtin_isanysubclass_vftbl(vftbl *sub,vftbl *super)
133 {
134         int base;
135         s4 res;
136         
137 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
138         cast_lock();
139 #endif
140
141         if ((base = super->baseval) <= 0)
142                 /* super is an interface */
143                 res = (sub->interfacetablelength > -base) &&
144                         (sub->interfacetable[base] != NULL);
145         else
146             res = (unsigned) (sub->baseval - base)
147                         <= (unsigned) (super->diffval);
148
149 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
150         cast_unlock();
151 #endif
152
153         return res;
154 }
155
156
157 /****************** function: builtin_instanceof *****************************
158
159         Checks if an object is an instance of some given class (or subclass of
160         that class). If class is an interface, checks if the interface is
161         implemented.
162         Return value:  1 ... obj is an instance of class or implements the interface
163                                    0 ... otherwise or if obj == NULL
164                          
165 *****************************************************************************/
166
167 /* XXX should use vftbl */
168 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
169 {
170 #ifdef DEBUG
171         log_text ("builtin_instanceof called");
172 #endif  
173         if (!obj) return 0;
174         return builtin_isanysubclass (obj->vftbl->class, class);
175 }
176
177
178
179 /**************** function: builtin_checkcast *******************************
180
181         The same as builtin_instanceof except that 1 is returned when
182         obj == NULL
183                           
184 ****************************************************************************/
185
186 /* XXX should use vftbl */
187 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
188 {
189 #ifdef DEBUG
190         log_text("builtin_checkcast called");
191 #endif
192
193         if (obj == NULL)
194                 return 1;
195         if (builtin_isanysubclass(obj->vftbl->class, class))
196                 return 1;
197
198 #if DEBUG
199         printf("#### checkcast failed ");
200         utf_display(obj->vftbl->class->name);
201         printf(" -> ");
202         utf_display(class->name);
203         printf("\n");
204 #endif
205
206         return 0;
207 }
208
209
210 /*********** internal function: builtin_descriptorscompatible ******************
211
212         Checks if two array type descriptors are assignment compatible
213         Return value:  1 ... target = desc is possible
214                                    0 ... otherwise
215                         
216 ******************************************************************************/
217
218 static s4 builtin_descriptorscompatible(arraydescriptor *desc,arraydescriptor *target)
219 {
220         if (desc==target) return 1;
221         if (desc->arraytype != target->arraytype) return 0;
222         if (desc->arraytype != ARRAYTYPE_OBJECT) return 1;
223         
224         /* {both arrays are arrays of references} */
225         if (desc->dimension == target->dimension) {
226                 /* an array which contains elements of interface types is allowed to be casted to Object (JOWENN)*/
227                 if ( (desc->elementvftbl->baseval<0) && (target->elementvftbl->baseval==1) ) return 1;
228                 return builtin_isanysubclass_vftbl(desc->elementvftbl,target->elementvftbl);
229         }
230         if (desc->dimension < target->dimension) return 0;
231
232         /* {desc has higher dimension than target} */
233         return builtin_isanysubclass_vftbl(pseudo_class_Arraystub_vftbl,target->elementvftbl);
234 }
235
236
237 /******************** function: builtin_checkarraycast ***********************
238
239         Checks if an object is really a subtype of the requested array type.
240         The object has to be an array to begin with. For simple arrays (int, short,
241         double, etc.) the types have to match exactly.
242         For arrays of objects, the type of elements in the array has to be a
243         subtype (or the same type) of the requested element type. For arrays of
244         arrays (which in turn can again be arrays of arrays), the types at the
245         lowest level have to satisfy the corresponding sub class relation.
246         
247         Return value:  1 ... cast is possible
248                                    0 ... otherwise
249         
250         ATTENTION: a cast with a NULL pointer is always possible.
251                         
252 *****************************************************************************/
253
254 s4 builtin_checkarraycast(java_objectheader *o, vftbl *target)
255 {
256         arraydescriptor *desc;
257         
258         if (!o) return 1;
259         if ((desc = o->vftbl->arraydesc) == NULL) return 0;
260
261         return builtin_descriptorscompatible(desc, target->arraydesc);
262 }
263
264
265 s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl *target)
266 {
267         if (!obj) return 1;
268         return builtin_checkarraycast(obj, target);
269 }
270
271
272 /************************** exception functions *******************************
273
274 ******************************************************************************/
275
276 java_objectheader *builtin_throw_exception(java_objectheader *local_exceptionptr)
277 {
278         if (verbose) {
279                 char logtext[MAXLOGTEXT];
280                 sprintf(logtext, "Builtin exception thrown: ");
281                 if (local_exceptionptr)
282                         utf_sprint(logtext + strlen(logtext), local_exceptionptr->vftbl->class->name);
283                 else {
284                         sprintf(logtext+strlen(logtext),"%s","Error: <Nullpointer instead of exception>");
285                         if (!proto_java_lang_ClassCastException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ClassCastException==0");
286                         if (!proto_java_lang_NullPointerException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_NullPointerException==0");
287                         if (!proto_java_lang_NullPointerException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_NullPointerException==0");
288                         if (!proto_java_lang_ArrayIndexOutOfBoundsException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ArrayIndexOutOfBoundsException==0");
289                         if (!proto_java_lang_NegativeArraySizeException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_NegativeArraySizeException==0");
290                         if (!proto_java_lang_OutOfMemoryError) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_OutOfMemoryError==0");
291                         if (!proto_java_lang_ArithmeticException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ArithmeticException==0");
292                         if (!proto_java_lang_ArrayStoreException) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ArrayStoreException==0");
293                         if (!proto_java_lang_ThreadDeath) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ThreadDeath==0");
294                         if (!proto_java_lang_ThreadDeath) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ThreadDeath==0");
295                         }
296                 log_text(logtext);
297         }
298         *exceptionptr = local_exceptionptr;
299         return local_exceptionptr;
300 }
301
302 void builtin_reset_exceptionptr()
303 {
304 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
305 #ifdef HAVE___THREAD
306         _exceptionptr = NULL;
307 #else
308         ((nativethread*) pthread_getspecific(tkey_exceptionptr))->_exceptionptr = 0;
309 #endif
310 #else
311         panic("builtin_reset_exceptionptr should not be used in this configuration");
312 #endif
313 }
314
315
316 /******************* function: builtin_canstore *******************************
317
318         Checks, if an object can be stored in an array.
319         Return value:  1 ... possible
320                                    0 ... otherwise
321
322 ******************************************************************************/
323
324 s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
325 {
326         arraydescriptor *desc;
327         arraydescriptor *valuedesc;
328         vftbl *componentvftbl;
329         vftbl *valuevftbl;
330     int dim_m1;
331         int base;
332         
333         if (!o) return 1;
334
335         /* The following is guaranteed (by verifier checks):
336          *
337          *     *) a->...vftbl->arraydesc != NULL
338          *     *) a->...vftbl->arraydesc->componentvftbl != NULL
339          *     *) o->vftbl is not an interface vftbl
340          */
341         
342         desc = a->header.objheader.vftbl->arraydesc;
343     componentvftbl = desc->componentvftbl;
344         valuevftbl = o->vftbl;
345
346     if ((dim_m1 = desc->dimension - 1) == 0) {
347                 s4 res;
348
349                 /* {a is a one-dimensional array} */
350                 /* {a is an array of references} */
351                 
352                 if (valuevftbl == componentvftbl)
353                         return 1;
354
355                 if ((base = componentvftbl->baseval) <= 0)
356                         /* an array of interface references */
357                         return (valuevftbl->interfacetablelength > -base &&
358                                         valuevftbl->interfacetable[base] != NULL);
359                 
360 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
361                 cast_lock();
362 #endif
363
364                 res = (unsigned)(valuevftbl->baseval - base)
365                         <= (unsigned)(componentvftbl->diffval);
366
367 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
368                 cast_unlock();
369 #endif
370
371                 return res;
372     }
373     /* {a has dimension > 1} */
374         /* {componentvftbl->arraydesc != NULL} */
375
376         /* check if o is an array */
377         if ((valuedesc = valuevftbl->arraydesc) == NULL)
378                 return 0;
379         /* {o is an array} */
380
381         return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
382 }
383
384
385 /* This is an optimized version where a is guaranteed to be one-dimensional */
386 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
387 {
388         arraydescriptor *desc;
389         vftbl *elementvftbl;
390         vftbl *valuevftbl;
391         int base;
392         s4 res;
393         
394         if (!o) return 1;
395
396         /* The following is guaranteed (by verifier checks):
397          *
398          *     *) a->...vftbl->arraydesc != NULL
399          *     *) a->...vftbl->arraydesc->elementvftbl != NULL
400          *     *) a->...vftbl->arraydesc->dimension == 1
401          *     *) o->vftbl is not an interface vftbl
402          */
403
404         desc = a->header.objheader.vftbl->arraydesc;
405     elementvftbl = desc->elementvftbl;
406         valuevftbl = o->vftbl;
407
408         /* {a is a one-dimensional array} */
409         
410         if (valuevftbl == elementvftbl)
411                 return 1;
412
413         if ((base = elementvftbl->baseval) <= 0)
414                 /* an array of interface references */
415                 return (valuevftbl->interfacetablelength > -base &&
416                                 valuevftbl->interfacetable[base] != NULL);
417         
418 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
419         cast_lock();
420 #endif
421
422         res = (unsigned)(valuevftbl->baseval - base)
423                 <= (unsigned)(elementvftbl->diffval);
424
425 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
426         cast_unlock();
427 #endif
428
429         return res;
430 }
431
432
433 /* This is an optimized version where a is guaranteed to be a
434  * one-dimensional array of a class type */
435 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
436 {
437         vftbl *elementvftbl;
438         vftbl *valuevftbl;
439         s4 res;
440         
441         if (!o) return 1;
442
443         /* The following is guaranteed (by verifier checks):
444          *
445          *     *) a->...vftbl->arraydesc != NULL
446          *     *) a->...vftbl->arraydesc->elementvftbl != NULL
447          *     *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
448          *     *) a->...vftbl->arraydesc->dimension == 1
449          *     *) o->vftbl is not an interface vftbl
450          */
451
452     elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
453         valuevftbl = o->vftbl;
454
455         /* {a is a one-dimensional array} */
456         
457         if (valuevftbl == elementvftbl)
458                 return 1;
459
460 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
461         cast_lock();
462 #endif
463
464         res = (unsigned)(valuevftbl->baseval - elementvftbl->baseval)
465                 <= (unsigned)(elementvftbl->diffval);
466
467 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
468         cast_unlock();
469 #endif
470
471         return res;
472 }
473
474
475 /******************** Function: builtin_new **********************************
476
477         Creates a new instance of class c on the heap.
478         Return value:  pointer to the object or NULL if no memory is
479                                    available
480                         
481 *****************************************************************************/
482
483 #define ALIGNMENT 3
484 #define align_size(size)        ((size + ((1 << ALIGNMENT) - 1)) & ~((1 << ALIGNMENT) - 1))
485
486 java_objectheader *builtin_new(classinfo *c)
487 {
488         java_objectheader *o;
489 /*DEBUGING - NOT THREAD SAFE*/
490 /*      static long depth=0;
491         depth++;
492         printf("Entering builtin_new:depth(%ld)",depth);*/
493
494         if (!c->initialized) {
495                 if (initverbose) {
496                         char logtext[MAXLOGTEXT];
497                         sprintf(logtext, "Initialize class ");
498                         utf_sprint(logtext + strlen(logtext), c->name);
499                         sprintf(logtext + strlen(logtext), " (from builtin_new)");
500                         log_text(logtext);
501                 }
502                 class_init(c);
503         }
504
505 #ifdef SIZE_FROM_CLASSINFO
506         c->alignedsize = align_size(c->instancesize);
507         o = heap_allocate(c->alignedsize, true, c->finalizer);
508 #else
509         o = heap_allocate(c->instancesize, true, c->finalizer);
510 #endif
511         if (!o) {
512                 /*DEBUGING - NOT THREAD SAFE*/
513                 /*printf("Leaving builtin_new: depth(%ld): NULL",depth);
514                 depth--;*/
515                 return NULL;
516         }
517         
518         memset(o, 0, c->instancesize);
519
520         o->vftbl = c->vftbl;
521
522         /*DEBUGING - NOT THREAD SAFE*/
523         /* printf("Leaving builtin_new: depth(%ld): object",depth);
524         depth--;*/
525         return o;
526 }
527
528 /********************** Function: builtin_newarray **************************
529
530         Creates an array with the given vftbl on the heap.
531
532         Return value:  pointer to the array or NULL if no memory is available
533
534     CAUTION: The given vftbl must be the vftbl of the *array* class,
535     not of the element class.
536
537 *****************************************************************************/
538
539 java_arrayheader *builtin_newarray(s4 size, vftbl *arrayvftbl)
540 {
541         java_arrayheader *a;
542         arraydescriptor *desc = arrayvftbl->arraydesc;
543         s4 dataoffset = desc->dataoffset;
544         s4 componentsize = desc->componentsize;
545         s4 actualsize;
546
547         if (size<0) {
548                 *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/NegativeArraySizeException")));
549                 return NULL;
550         }
551 #ifdef SIZE_FROM_CLASSINFO
552         actualsize = align_size(dataoffset + size * componentsize);
553 #else
554         actualsize = dataoffset + size * componentsize;
555 #endif
556
557         if (((u4)actualsize)<((u4)size)) { /* overflow */
558                 *exceptionptr = native_new_and_init(loader_load(utf_new_char("java/lang/OutOfMemoryError")));
559                 return NULL;
560         }
561         a = heap_allocate(actualsize,
562                                           (desc->arraytype == ARRAYTYPE_OBJECT),
563                                           NULL);
564
565         if (!a) return NULL;
566         memset(a, 0, actualsize);
567
568
569         /*printf("builtin_newarray: Created an array of size : %d\n",size);*/
570
571         a->objheader.vftbl = arrayvftbl;
572         a->size = size;
573 #ifdef SIZE_FROM_CLASSINFO
574         a->alignedsize = actualsize;
575 #endif
576
577         return a;
578 }
579
580
581 /********************** Function: builtin_anewarray *************************
582
583         Creates an array of references to the given class type on the heap.
584
585         Return value:  pointer to the array or NULL if no memory is available
586
587     XXX This function does not do The Right Thing, because it uses a
588     classinfo pointer at runtime. builtin_newarray should be used
589     instead.
590
591 *****************************************************************************/
592
593 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
594 {
595 /*
596         printf("builtin_anewarray: classvftbl: %d\n",component->classvftbl);
597         printf("builtin_anewarray: baseval: %d\n",component->vftbl->baseval);
598         utf_display(component->vftbl->class->name);
599         printf("\nbuiltin_anewarray: linked: %d\n",component->linked);
600         utf_display(component->super->name);*/
601         return (java_objectarray*) builtin_newarray(size, class_array_of(component)->vftbl);
602 }
603
604
605 /******************** Function: builtin_newarray_int ***********************
606
607         Creates an array of 32 bit Integers on the heap.
608
609         Return value:  pointer to the array or NULL if no memory is available
610
611 *****************************************************************************/
612
613 java_intarray *builtin_newarray_int(s4 size)
614 {
615         return (java_intarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
616 }
617
618
619 /******************** Function: builtin_newarray_long ***********************
620
621         Creates an array of 64 bit Integers on the heap.
622
623         Return value:  pointer to the array or NULL if no memory is available
624
625 *****************************************************************************/
626
627 java_longarray *builtin_newarray_long(s4 size)
628 {
629         return (java_longarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
630 }
631
632
633 /******************** function: builtin_newarray_float ***********************
634
635         Creates an array of 32 bit IEEE floats on the heap.
636
637         Return value:  pointer to the array or NULL if no memory is available
638
639 *****************************************************************************/
640
641 java_floatarray *builtin_newarray_float(s4 size)
642 {
643         return (java_floatarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
644 }
645
646
647 /******************** function: builtin_newarray_double ***********************
648
649         Creates an array of 64 bit IEEE floats on the heap.
650
651         Return value:  pointer to the array or NULL if no memory is available
652
653 *****************************************************************************/
654
655 java_doublearray *builtin_newarray_double(s4 size)
656 {
657         return (java_doublearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
658 }
659
660
661 /******************** function: builtin_newarray_byte ***********************
662
663         Creates an array of 8 bit Integers on the heap.
664
665         Return value:  pointer to the array or NULL if no memory is available
666
667 *****************************************************************************/
668
669 java_bytearray *builtin_newarray_byte(s4 size)
670 {
671         return (java_bytearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
672 }
673
674
675 /******************** function: builtin_newarray_char ************************
676
677         Creates an array of characters on the heap.
678
679         Return value:  pointer to the array or NULL if no memory is available
680
681 *****************************************************************************/
682
683 java_chararray *builtin_newarray_char(s4 size)
684 {
685         return (java_chararray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
686 }
687
688
689 /******************** function: builtin_newarray_short ***********************
690
691         Creates an array of 16 bit Integers on the heap.
692
693         Return value:  pointer to the array or NULL if no memory is available
694
695 *****************************************************************************/
696
697 java_shortarray *builtin_newarray_short(s4 size)
698 {
699         return (java_shortarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
700 }
701
702
703 /******************** function: builtin_newarray_boolean ************************
704
705         Creates an array of bytes on the heap. The array is designated as an array
706         of booleans (important for casts)
707         
708         Return value:  pointer to the array or NULL if no memory is available
709
710 *****************************************************************************/
711
712 java_booleanarray *builtin_newarray_boolean(s4 size)
713 {
714         return (java_booleanarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
715 }
716
717
718 /**************** function: builtin_nmultianewarray ***************************
719
720         Creates a multi-dimensional array on the heap. The dimensions are passed in
721         an array of longs.
722
723     Arguments:
724         n............number of dimensions to create
725         arrayvftbl...vftbl of the array class
726         dims.........array containing the size of each dimension to create
727
728         Return value:  pointer to the array or NULL if no memory is available
729
730 ******************************************************************************/
731
732         /* Helper functions */
733
734 java_arrayheader *builtin_nmultianewarray (int n, vftbl *arrayvftbl, long *dims)
735 {
736         int size, i;
737         java_arrayheader *a;
738         vftbl *componentvftbl;
739
740         /* create this dimension */
741         size = (int) dims[0];
742         a = builtin_newarray(size,arrayvftbl);
743         if (!a) return NULL;
744
745         /* if this is the last dimension return */
746         if (!--n) return a;
747
748         /* get the vftbl of the components to create */
749         componentvftbl = arrayvftbl->arraydesc->componentvftbl;
750
751         /* The verifier guarantees this. */
752         /* if (!componentvftbl) */
753         /*      panic ("multianewarray with too many dimensions"); */
754
755         /* create the component arrays */
756         for (i = 0; i < size; i++) {
757                 java_arrayheader *ea = 
758                         builtin_nmultianewarray(n,componentvftbl,dims+1);
759                 if (!ea) return NULL;
760                 ((java_objectarray*)a)->data[i] = (java_objectheader *) ea;
761         }
762
763         return a;
764 }
765
766
767 /*****************************************************************************
768                                           METHOD LOGGING
769
770         Various functions for printing a message at method entry or exit (for
771         debugging)
772         
773 *****************************************************************************/
774
775 u4 methodindent = 0;
776
777 java_objectheader *builtin_trace_exception(java_objectheader *_exceptionptr,
778                                                                                    methodinfo *method,
779                                                                                    int *pos, 
780                                                                                    int noindent)
781 {
782         if (!noindent) {
783                 if (methodindent)
784                         methodindent--;
785                 else
786                         log_text("WARNING: unmatched methodindent--");
787         }
788         if (verbose || runverbose) {
789                 printf("Exception ");
790                 if (_exceptionptr) {
791                         utf_display_classname(_exceptionptr->vftbl->class->name);
792
793                 } else {
794                         printf("Error: <Nullpointer instead of exception>");
795                         if (!proto_java_lang_ClassCastException) printf("%s","proto_java_lang_ClassCastException==0");
796                         if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0");
797                         if (!proto_java_lang_NullPointerException) printf("%s","proto_java_lang_NullPointerException==0");
798                         if (!proto_java_lang_ArrayIndexOutOfBoundsException) printf("%s","proto_java_lang_ArrayIndexOutOfBoundsException==0");
799                         if (!proto_java_lang_NegativeArraySizeException) printf("%s","proto_java_lang_NegativeArraySizeException==0");
800                         if (!proto_java_lang_OutOfMemoryError) printf("%s","proto_java_lang_OutOfMemoryError==0");
801                         if (!proto_java_lang_ArithmeticException) printf("%s","proto_java_lang_ArithmeticException==0");
802                         if (!proto_java_lang_ArrayStoreException) printf("%s","proto_java_lang_ArrayStoreException==0");
803                         if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0");
804                         if (!proto_java_lang_ThreadDeath) printf("%s","proto_java_lang_ThreadDeath==0");
805
806                 }
807                 printf(" thrown in ");
808
809                 if (method) {
810                         utf_display_classname(method->class->name);
811                         printf(".");
812                         utf_display(method->name);
813                         if (method->flags & ACC_SYNCHRONIZED)
814                                 printf("(SYNC)");
815                         else
816                                 printf("(NOSYNC)");
817                         printf("(%p) at position %p\n", method->entrypoint, pos);
818
819                 } else
820                         printf("call_java_method\n");
821                 fflush (stdout);
822         }
823
824         return _exceptionptr;
825 }
826
827
828 #ifdef TRACE_ARGS_NUM
829 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3, s8 a4, s8 a5,
830 #if TRACE_ARGS_NUM > 6
831                                                 s8 a6, s8 a7,
832 #endif
833                                                 methodinfo *method)
834 {
835         int i;
836         char logtext[MAXLOGTEXT];
837         for (i = 0; i < methodindent; i++)
838                 logtext[i] = '\t';
839
840         sprintf(logtext + methodindent, "called: ");
841         utf_sprint(logtext + strlen(logtext), method->class->name);
842         sprintf(logtext + strlen(logtext), ".");
843         utf_sprint(logtext + strlen(logtext), method->name);
844         utf_sprint(logtext + strlen(logtext), method->descriptor);
845
846         if ( method->flags & ACC_PUBLIC )       sprintf (logtext + strlen(logtext)," PUBLIC");
847         if ( method->flags & ACC_PRIVATE )      sprintf (logtext + strlen(logtext)," PRIVATE");
848         if ( method->flags & ACC_PROTECTED )    sprintf (logtext + strlen(logtext)," PROTECTED");
849         if ( method->flags & ACC_STATIC )       sprintf (logtext + strlen(logtext)," STATIC");
850         if ( method->flags & ACC_FINAL )        sprintf (logtext + strlen(logtext)," FINAL");
851         if ( method->flags & ACC_SYNCHRONIZED ) sprintf (logtext + strlen(logtext)," SYNCHRONIZED");
852         if ( method->flags & ACC_VOLATILE )     sprintf (logtext + strlen(logtext)," VOLATILE");
853         if ( method->flags & ACC_TRANSIENT )    sprintf (logtext + strlen(logtext)," TRANSIENT");
854         if ( method->flags & ACC_NATIVE )       sprintf (logtext + strlen(logtext)," NATIVE");
855         if ( method->flags & ACC_INTERFACE )    sprintf (logtext + strlen(logtext)," INTERFACE");
856         if ( method->flags & ACC_ABSTRACT )     sprintf (logtext + strlen(logtext)," ABSTRACT");
857         
858
859         sprintf(logtext + strlen(logtext), "(");
860
861         switch (method->paramcount) {
862         case 0:
863                 break;
864
865 #if defined(__I386__) || defined(__POWERPC__)
866         case 1:
867                 sprintf(logtext+strlen(logtext), "%llx", a0);
868                 break;
869
870         case 2:
871                 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
872                 break;
873
874         case 3:
875                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
876                 break;
877
878         case 4:
879                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
880                                 a0,   a1,   a2,   a3);
881                 break;
882
883         case 5:
884                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
885                                 a0,   a1,   a2,   a3,   a4);
886                 break;
887
888         case 6:
889                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
890                                 a0,   a1,   a2,   a3,   a4,   a5);
891                 break;
892
893 #if TRACE_ARGS_NUM > 6
894         case 7:
895                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
896                                 a0,   a1,   a2,   a3,   a4,   a5,   a6);
897                 break;
898
899         case 8:
900                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
901                                 a0,   a1,   a2,   a3,   a4,   a5,   a6,   a7);
902                 break;
903
904         default:
905                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
906                                 a0,   a1,   a2,   a3,   a4,   a5,   a6,   a7,   method->paramcount - 8);
907                 break;
908 #else
909         default:
910                 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
911                                 a0,   a1,   a2,   a3,   a4,   a5,   method->paramcount - 6);
912                 break;
913 #endif
914 #else
915         case 1:
916                 sprintf(logtext+strlen(logtext), "%lx", a0);
917                 break;
918
919         case 2:
920                 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
921                 break;
922
923         case 3:
924                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
925                 break;
926
927         case 4:
928                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
929                                 a0,  a1,  a2,  a3);
930                 break;
931
932         case 5:
933                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
934                                 a0,  a1,  a2,  a3,  a4);
935                 break;
936
937         case 6:
938                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
939                                 a0,  a1,  a2,  a3,  a4,  a5);
940                 break;
941
942 #if TRACE_ARGS_NUM > 6
943         case 7:
944                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
945                                 a0,  a1,  a2,  a3,  a4,  a5,  a6);
946                 break;
947
948         case 8:
949                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
950                                 a0,  a1,  a2,  a3,  a4,  a5,  a6,  a7);
951                 break;
952
953         default:
954                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
955                                 a0,  a1,  a2,  a3,  a4,  a5,  a6,  a7,  method->paramcount - 8);
956                 break;
957 #else
958         default:
959                 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
960                                 a0,  a1,  a2,  a3,  a4,  a5,   method->paramcount - 6);
961                 break;
962 #endif
963 #endif
964         }
965
966         sprintf(logtext + strlen(logtext), ")");
967         log_text(logtext);
968
969         methodindent++;
970 }
971 #endif
972
973
974 void builtin_displaymethodstart(methodinfo *method)
975 {
976         char logtext[MAXLOGTEXT];
977         sprintf(logtext, "                                                                                              ");
978         sprintf(logtext + methodindent, "called: ");
979         utf_sprint(logtext + strlen(logtext), method->class->name);
980         sprintf(logtext + strlen(logtext), ".");
981         utf_sprint(logtext + strlen(logtext), method->name);
982         utf_sprint(logtext + strlen(logtext), method->descriptor);
983
984         if ( method->flags & ACC_PUBLIC )       sprintf (logtext + strlen(logtext)," PUBLIC");
985         if ( method->flags & ACC_PRIVATE )      sprintf (logtext + strlen(logtext)," PRIVATE");
986         if ( method->flags & ACC_PROTECTED )    sprintf (logtext + strlen(logtext)," PROTECTED");
987         if ( method->flags & ACC_STATIC )       sprintf (logtext + strlen(logtext)," STATIC");
988         if ( method->flags & ACC_FINAL )        sprintf (logtext + strlen(logtext)," FINAL");
989         if ( method->flags & ACC_SYNCHRONIZED ) sprintf (logtext + strlen(logtext)," SYNCHRONIZED");
990         if ( method->flags & ACC_VOLATILE )     sprintf (logtext + strlen(logtext)," VOLATILE");
991         if ( method->flags & ACC_TRANSIENT )    sprintf (logtext + strlen(logtext)," TRANSIENT");
992         if ( method->flags & ACC_NATIVE )       sprintf (logtext + strlen(logtext)," NATIVE");
993         if ( method->flags & ACC_INTERFACE )    sprintf (logtext + strlen(logtext)," INTERFACE");
994         if ( method->flags & ACC_ABSTRACT )     sprintf (logtext + strlen(logtext)," ABSTRACT");
995
996         log_text(logtext);
997         methodindent++;
998 }
999
1000
1001 void builtin_displaymethodstop(methodinfo *method, s8 l, double d, float f)
1002 {
1003         int i;
1004         char logtext[MAXLOGTEXT];
1005         for (i = 0; i < methodindent; i++)
1006                 logtext[i] = '\t';
1007         if (methodindent)
1008                 methodindent--;
1009         else
1010                 log_text("WARNING: unmatched methodindent--");
1011
1012         sprintf(logtext + methodindent, "finished: ");
1013         utf_sprint(logtext + strlen(logtext), method->class->name);
1014         sprintf(logtext + strlen(logtext), ".");
1015         utf_sprint(logtext + strlen(logtext), method->name);
1016         utf_sprint(logtext + strlen(logtext), method->descriptor);
1017
1018         switch (method->returntype) {
1019         case TYPE_INT:
1020                 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1021                 break;
1022
1023         case TYPE_LONG:
1024 #if defined(__I386__) || defined(__POWERPC__)
1025                 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1026 #else
1027                 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1028 #endif
1029                 break;
1030
1031         case TYPE_ADDRESS:
1032 #if defined(__I386__) || defined(__POWERPC__)
1033                 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1034 #else
1035                 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1036 #endif
1037                 break;
1038
1039         case TYPE_FLOAT:
1040                 sprintf(logtext + strlen(logtext), "->%g", f);
1041                 break;
1042
1043         case TYPE_DOUBLE:
1044                 sprintf(logtext + strlen(logtext), "->%g", d);
1045                 break;
1046         }
1047         log_text(logtext);
1048 }
1049
1050
1051 void builtin_displaymethodexception(methodinfo *method)
1052 {
1053         int i;
1054         char logtext[MAXLOGTEXT];
1055         for (i = 0; i < methodindent; i++)
1056                 logtext[i] = '\t';
1057         sprintf(logtext + methodindent, "exception abort: ");
1058         utf_sprint(logtext + strlen(logtext), method->class->name);
1059         sprintf(logtext + strlen(logtext), ".");
1060         utf_sprint(logtext + strlen(logtext), method->name);
1061         utf_sprint(logtext + strlen(logtext), method->descriptor);
1062         log_text(logtext);
1063 }
1064
1065
1066 /****************************************************************************
1067                          SYNCHRONIZATION FUNCTIONS
1068 *****************************************************************************/
1069
1070 /*
1071  * Lock the mutex of an object.
1072  */
1073 void internal_lock_mutex_for_object(java_objectheader *object)
1074 {
1075 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1076         mutexHashEntry *entry;
1077         int hashValue;
1078
1079         assert(object != 0);
1080
1081         hashValue = MUTEX_HASH_VALUE(object);
1082         entry = &mutexHashTable[hashValue];
1083
1084         if (entry->object != 0) {
1085                 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1086                         entry->object = 0;
1087                         entry->mutex.holder = 0;
1088                         entry->mutex.count = 0;
1089                         entry->mutex.muxWaiters = 0;
1090
1091                 } else {
1092                         while (entry->next != 0 && entry->object != object)
1093                                 entry = entry->next;
1094
1095                         if (entry->object != object) {
1096                                 entry->next = firstFreeOverflowEntry;
1097                                 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1098
1099                                 entry = entry->next;
1100                                 entry->object = 0;
1101                                 entry->next = 0;
1102                                 assert(entry->conditionCount == 0);
1103                         }
1104                 }
1105
1106         } else {
1107                 entry->mutex.holder = 0;
1108                 entry->mutex.count = 0;
1109                 entry->mutex.muxWaiters = 0;
1110         }
1111
1112         if (entry->object == 0)
1113                 entry->object = object;
1114         
1115         internal_lock_mutex(&entry->mutex);
1116 #endif
1117 }
1118
1119
1120 /*
1121  * Unlocks the mutex of an object.
1122  */
1123 void internal_unlock_mutex_for_object (java_objectheader *object)
1124 {
1125 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1126         int hashValue;
1127         mutexHashEntry *entry;
1128
1129         hashValue = MUTEX_HASH_VALUE(object);
1130         entry = &mutexHashTable[hashValue];
1131
1132         if (entry->object == object) {
1133                 internal_unlock_mutex(&entry->mutex);
1134
1135         } else {
1136                 while (entry->next != 0 && entry->next->object != object)
1137                         entry = entry->next;
1138
1139                 assert(entry->next != 0);
1140
1141                 internal_unlock_mutex(&entry->next->mutex);
1142
1143                 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1144                         mutexHashEntry *unlinked = entry->next;
1145
1146                         entry->next = unlinked->next;
1147                         unlinked->next = firstFreeOverflowEntry;
1148                         firstFreeOverflowEntry = unlinked;
1149                 }
1150         }
1151 #endif
1152 }
1153
1154
1155 void builtin_monitorenter(java_objectheader *o)
1156 {
1157 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1158         int hashValue;
1159
1160         assert(blockInts == 0);
1161
1162         ++blockInts;
1163
1164         hashValue = MUTEX_HASH_VALUE(o);
1165         if (mutexHashTable[hashValue].object == o 
1166                 && mutexHashTable[hashValue].mutex.holder == currentThread)
1167                 ++mutexHashTable[hashValue].mutex.count;
1168         else
1169                 internal_lock_mutex_for_object(o);
1170
1171         --blockInts;
1172
1173         assert(blockInts == 0);
1174 #endif
1175 }
1176
1177
1178 void builtin_monitorexit (java_objectheader *o)
1179 {
1180 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1181         int hashValue;
1182
1183         assert(blockInts == 0);
1184
1185         ++blockInts;
1186
1187         hashValue = MUTEX_HASH_VALUE(o);
1188         if (mutexHashTable[hashValue].object == o) {
1189                 if (mutexHashTable[hashValue].mutex.count == 1
1190                         && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1191                         internal_unlock_mutex_for_object(o);
1192                 else
1193                         --mutexHashTable[hashValue].mutex.count;
1194
1195         } else
1196                 internal_unlock_mutex_for_object(o);
1197
1198         --blockInts;
1199
1200         assert(blockInts == 0);
1201 #endif
1202 }
1203
1204
1205 /*****************************************************************************
1206                           MISCELLANEOUS HELPER FUNCTIONS
1207 *****************************************************************************/
1208
1209
1210
1211 /*********** Functions for integer divisions *****************************
1212  
1213         On some systems (eg. DEC ALPHA), integer division is not supported by the
1214         CPU. These helper functions implement the missing functionality.
1215
1216 ******************************************************************************/
1217
1218 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1219 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1220
1221
1222 /************** Functions for long arithmetics *******************************
1223
1224         On systems where 64 bit Integers are not supported by the CPU, these
1225         functions are needed.
1226
1227 ******************************************************************************/
1228
1229
1230 s8 builtin_ladd(s8 a, s8 b)
1231
1232 #if U8_AVAILABLE
1233         return a + b; 
1234 #else
1235         return builtin_i2l(0);
1236 #endif
1237 }
1238
1239 s8 builtin_lsub(s8 a, s8 b) 
1240
1241 #if U8_AVAILABLE
1242         return a - b; 
1243 #else
1244         return builtin_i2l(0);
1245 #endif
1246 }
1247
1248 s8 builtin_lmul(s8 a, s8 b) 
1249
1250 #if U8_AVAILABLE
1251         return a * b; 
1252 #else
1253         return builtin_i2l(0);
1254 #endif
1255 }
1256
1257 s8 builtin_ldiv(s8 a, s8 b) 
1258
1259 #if U8_AVAILABLE
1260         return a / b; 
1261 #else
1262         return builtin_i2l(0);
1263 #endif
1264 }
1265
1266 s8 builtin_lrem(s8 a, s8 b) 
1267
1268 #if U8_AVAILABLE
1269         return a % b; 
1270 #else
1271         return builtin_i2l(0);
1272 #endif
1273 }
1274
1275 s8 builtin_lshl(s8 a, s4 b) 
1276
1277 #if U8_AVAILABLE
1278         return a << (b & 63);
1279 #else
1280         return builtin_i2l(0);
1281 #endif
1282 }
1283
1284 s8 builtin_lshr(s8 a, s4 b) 
1285
1286 #if U8_AVAILABLE
1287         return a >> (b & 63);
1288 #else
1289         return builtin_i2l(0);
1290 #endif
1291 }
1292
1293 s8 builtin_lushr(s8 a, s4 b) 
1294
1295 #if U8_AVAILABLE
1296         return ((u8) a) >> (b & 63);
1297 #else
1298         return builtin_i2l(0);
1299 #endif
1300 }
1301
1302 s8 builtin_land(s8 a, s8 b) 
1303
1304 #if U8_AVAILABLE
1305         return a & b; 
1306 #else
1307         return builtin_i2l(0);
1308 #endif
1309 }
1310
1311 s8 builtin_lor(s8 a, s8 b) 
1312
1313 #if U8_AVAILABLE
1314         return a | b; 
1315 #else
1316         return builtin_i2l(0);
1317 #endif
1318 }
1319
1320 s8 builtin_lxor(s8 a, s8 b) 
1321
1322 #if U8_AVAILABLE
1323         return a ^ b; 
1324 #else
1325         return builtin_i2l(0);
1326 #endif
1327 }
1328
1329 s8 builtin_lneg(s8 a) 
1330
1331 #if U8_AVAILABLE
1332         return -a;
1333 #else
1334         return builtin_i2l(0);
1335 #endif
1336 }
1337
1338 s4 builtin_lcmp(s8 a, s8 b) 
1339
1340 #if U8_AVAILABLE
1341         if (a < b) return -1;
1342         if (a > b) return 1;
1343         return 0;
1344 #else
1345         return 0;
1346 #endif
1347 }
1348
1349
1350
1351
1352
1353 /*********** Functions for floating point operations *************************/
1354
1355 float builtin_fadd(float a, float b)
1356 {
1357         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1358         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1359         if (finitef(a)) {
1360                 if (finitef(b))
1361                         return a + b;
1362                 else
1363                         return b;
1364         }
1365         else {
1366                 if (finitef(b))
1367                         return a;
1368                 else {
1369                         if (copysignf(1.0, a) == copysignf(1.0, b))
1370                                 return a;
1371                         else
1372                                 return intBitsToFloat(FLT_NAN);
1373                 }
1374         }
1375 }
1376
1377
1378 float builtin_fsub(float a, float b)
1379 {
1380         return builtin_fadd(a, builtin_fneg(b));
1381 }
1382
1383
1384 float builtin_fmul(float a, float b)
1385 {
1386         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1387         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1388         if (finitef(a)) {
1389                 if (finitef(b)) return a * b;
1390                 else {
1391                         if (a == 0) return intBitsToFloat(FLT_NAN);
1392                         else return copysignf(b, copysignf(1.0, b)*a);
1393                 }
1394         }
1395         else {
1396                 if (finitef(b)) {
1397                         if (b == 0) return intBitsToFloat(FLT_NAN);
1398                         else return copysignf(a, copysignf(1.0, a)*b);
1399                 }
1400                 else {
1401                         return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1402                 }
1403         }
1404 }
1405
1406
1407 float builtin_fdiv(float a, float b)
1408 {
1409         if (finitef(a) && finitef(b)) {
1410                 if (b != 0)
1411                         return a / b;
1412                 else {
1413                         if (a > 0)
1414                                 return intBitsToFloat(FLT_POSINF);
1415                         else if (a < 0)
1416                                 return intBitsToFloat(FLT_NEGINF);
1417                 }
1418         }
1419         return intBitsToFloat(FLT_NAN);
1420 }
1421
1422
1423 float builtin_frem(float a, float b)
1424 {
1425         return fmodf(a, b);
1426 }
1427
1428
1429 float builtin_fneg(float a)
1430 {
1431         if (isnanf(a)) return a;
1432         else {
1433                 if (finitef(a)) return -a;
1434                 else return copysignf(a, -copysignf(1.0, a));
1435         }
1436 }
1437
1438
1439 s4 builtin_fcmpl(float a, float b)
1440 {
1441         if (isnanf(a)) return -1;
1442         if (isnanf(b)) return -1;
1443         if (!finitef(a) || !finitef(b)) {
1444                 a = finitef(a) ? 0 : copysignf(1.0,     a);
1445                 b = finitef(b) ? 0 : copysignf(1.0, b);
1446         }
1447         if (a > b) return 1;
1448         if (a == b) return 0;
1449         return -1;
1450 }
1451
1452
1453 s4 builtin_fcmpg(float a, float b)
1454 {
1455         if (isnanf(a)) return 1;
1456         if (isnanf(b)) return 1;
1457         if (!finitef(a) || !finitef(b)) {
1458                 a = finitef(a) ? 0 : copysignf(1.0, a);
1459                 b = finitef(b) ? 0 : copysignf(1.0, b);
1460         }
1461         if (a > b) return 1;
1462         if (a == b) return 0;
1463         return -1;
1464 }
1465
1466
1467
1468 /************************* Functions for doubles ****************************/
1469
1470 double builtin_dadd(double a, double b)
1471 {
1472         if (isnan(a)) return longBitsToDouble(DBL_NAN);
1473         if (isnan(b)) return longBitsToDouble(DBL_NAN);
1474         if (finite(a)) {
1475                 if (finite(b)) return a + b;
1476                 else return b;
1477         }
1478         else {
1479                 if (finite(b)) return a;
1480                 else {
1481                         if (copysign(1.0, a)==copysign(1.0, b)) return a;
1482                         else return longBitsToDouble(DBL_NAN);
1483                 }
1484         }
1485 }
1486
1487
1488 double builtin_dsub(double a, double b)
1489 {
1490         return builtin_dadd(a, builtin_dneg(b));
1491 }
1492
1493
1494 double builtin_dmul(double a, double b)
1495 {
1496         if (isnan(a)) return longBitsToDouble(DBL_NAN);
1497         if (isnan(b)) return longBitsToDouble(DBL_NAN);
1498         if (finite(a)) {
1499                 if (finite(b)) return a * b;
1500                 else {
1501                         if (a == 0) return longBitsToDouble(DBL_NAN);
1502                         else return copysign(b, copysign(1.0, b) * a);
1503                 }
1504         }
1505         else {
1506                 if (finite(b)) {
1507                         if (b == 0) return longBitsToDouble(DBL_NAN);
1508                         else return copysign(a, copysign(1.0, a) * b);
1509                 }
1510                 else {
1511                         return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1512                 }
1513         }
1514 }
1515
1516
1517 double builtin_ddiv(double a, double b)
1518 {
1519         if (finite(a)) {
1520                 if (finite(b)) {
1521                         return a / b;
1522
1523                 } else {
1524                         if (isnan(b))
1525                                 return longBitsToDouble(DBL_NAN);
1526                         else
1527                                 return copysign(0.0, b);
1528                 }
1529
1530         } else {
1531                 if (finite(b)) {
1532                         if (a > 0)
1533                                 return longBitsToDouble(DBL_POSINF);
1534                         else if (a < 0)
1535                                 return longBitsToDouble(DBL_NEGINF);
1536
1537                 } else
1538                         return longBitsToDouble(DBL_NAN);
1539         }
1540
1541 /*      if (finite(a) && finite(b)) { */
1542 /*              if (b != 0) */
1543 /*                      return a / b; */
1544 /*              else { */
1545 /*                      if (a > 0) */
1546 /*                              return longBitsToDouble(DBL_POSINF); */
1547 /*                      else if (a < 0) */
1548 /*                              return longBitsToDouble(DBL_NEGINF); */
1549 /*              } */
1550 /*      } */
1551
1552         /* keep compiler happy */
1553         return 0;
1554 }
1555
1556
1557 double builtin_drem(double a, double b)
1558 {
1559         return fmod(a, b);
1560 }
1561
1562
1563 double builtin_dneg(double a)
1564 {
1565         if (isnan(a)) return a;
1566         else {
1567                 if (finite(a)) return -a;
1568                 else return copysign(a, -copysign(1.0, a));
1569         }
1570 }
1571
1572
1573 s4 builtin_dcmpl(double a, double b)
1574 {
1575         if (isnan(a)) return -1;
1576         if (isnan(b)) return -1;
1577         if (!finite(a) || !finite(b)) {
1578                 a = finite(a) ? 0 : copysign(1.0, a);
1579                 b = finite(b) ? 0 : copysign(1.0, b);
1580         }
1581         if (a > b) return 1;
1582         if (a == b) return 0;
1583         return -1;
1584 }
1585
1586
1587 s4 builtin_dcmpg(double a, double b)
1588 {
1589         if (isnan(a)) return 1;
1590         if (isnan(b)) return 1;
1591         if (!finite(a) || !finite(b)) {
1592                 a = finite(a) ? 0 : copysign(1.0, a);
1593                 b = finite(b) ? 0 : copysign(1.0, b);
1594         }
1595         if (a > b) return 1;
1596         if (a == b) return 0;
1597         return -1;
1598 }
1599
1600
1601 /*********************** Conversion operations ****************************/
1602
1603 s8 builtin_i2l(s4 i)
1604 {
1605 #if U8_AVAILABLE
1606         return i;
1607 #else
1608         s8 v;
1609         v.high = 0;
1610         v.low = i;
1611         return v;
1612 #endif
1613 }
1614
1615
1616 float builtin_i2f(s4 a)
1617 {
1618         float f = (float) a;
1619         return f;
1620 }
1621
1622
1623 double builtin_i2d(s4 a)
1624 {
1625         double d = (double) a;
1626         return d;
1627 }
1628
1629
1630 s4 builtin_l2i(s8 l)
1631 {
1632 #if U8_AVAILABLE
1633         return (s4) l;
1634 #else
1635         return l.low;
1636 #endif
1637 }
1638
1639
1640 float builtin_l2f(s8 a)
1641 {
1642 #if U8_AVAILABLE
1643         float f = (float) a;
1644         return f;
1645 #else
1646         return 0.0;
1647 #endif
1648 }
1649
1650
1651 double builtin_l2d(s8 a)
1652 {
1653 #if U8_AVAILABLE
1654         double d = (double) a;
1655         return d;
1656 #else
1657         return 0.0;
1658 #endif
1659 }
1660
1661
1662 s4 builtin_f2i(float a) 
1663 {
1664
1665         return builtin_d2i((double) a);
1666
1667         /*      float f;
1668         
1669                 if (isnanf(a))
1670                 return 0;
1671                 if (finitef(a)) {
1672                 if (a > 2147483647)
1673                 return 2147483647;
1674                 if (a < (-2147483648))
1675                 return (-2147483648);
1676                 return (s4) a;
1677                 }
1678                 f = copysignf((float) 1.0, a);
1679                 if (f > 0)
1680                 return 2147483647;
1681                 return (-2147483648); */
1682 }
1683
1684
1685 s8 builtin_f2l(float a)
1686 {
1687
1688         return builtin_d2l((double) a);
1689
1690         /*      float f;
1691         
1692                 if (finitef(a)) {
1693                 if (a > 9223372036854775807L)
1694                 return 9223372036854775807L;
1695                 if (a < (-9223372036854775808L))
1696                 return (-9223372036854775808L);
1697                 return (s8) a;
1698                 }
1699                 if (isnanf(a))
1700                 return 0;
1701                 f = copysignf((float) 1.0, a);
1702                 if (f > 0)
1703                 return 9223372036854775807L;
1704                 return (-9223372036854775808L); */
1705 }
1706
1707
1708 double builtin_f2d(float a)
1709 {
1710         if (finitef(a)) return (double) a;
1711         else {
1712                 if (isnanf(a))
1713                         return longBitsToDouble(DBL_NAN);
1714                 else
1715                         return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1716         }
1717 }
1718
1719
1720 s4 builtin_d2i(double a) 
1721
1722         double d;
1723         
1724         if (finite(a)) {
1725                 if (a >= 2147483647)
1726                         return 2147483647;
1727                 if (a <= (-2147483647-1))
1728                         return (-2147483647-1);
1729                 return (s4) a;
1730         }
1731         if (isnan(a))
1732                 return 0;
1733         d = copysign(1.0, a);
1734         if (d > 0)
1735                 return 2147483647;
1736         return (-2147483647-1);
1737 }
1738
1739
1740 s8 builtin_d2l(double a)
1741 {
1742         double d;
1743         
1744         if (finite(a)) {
1745                 if (a >= 9223372036854775807LL)
1746                         return 9223372036854775807LL;
1747                 if (a <= (-9223372036854775807LL-1))
1748                         return (-9223372036854775807LL-1);
1749                 return (s8) a;
1750         }
1751         if (isnan(a))
1752                 return 0;
1753         d = copysign(1.0, a);
1754         if (d > 0)
1755                 return 9223372036854775807LL;
1756         return (-9223372036854775807LL-1);
1757 }
1758
1759
1760 float builtin_d2f(double a)
1761 {
1762         if (finite(a))
1763                 return (float) a;
1764         else {
1765                 if (isnan(a))
1766                         return intBitsToFloat(FLT_NAN);
1767                 else
1768                         return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
1769         }
1770 }
1771
1772
1773 /* used to convert FLT_xxx defines into float values */
1774
1775 inline float intBitsToFloat(s4 i)
1776 {
1777         imm_union imb;
1778
1779         imb.i = i;
1780         return imb.f;
1781 }
1782
1783
1784 /* used to convert DBL_xxx defines into double values */
1785
1786 inline float longBitsToDouble(s8 l)
1787 {
1788         imm_union imb;
1789
1790         imb.l = l;
1791         return imb.d;
1792 }
1793
1794
1795 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
1796 {
1797         return (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
1798 }
1799
1800 s4 builtin_dummy()
1801 {
1802         panic("Internal error: builtin_dummy called (native function is missing)");
1803         return 0; /* for the compiler */
1804 }
1805
1806
1807 inline methodinfo *builtin_asm_get_threadrootmethod() {
1808         return *threadrootmethod;
1809 }
1810
1811
1812 inline void* 
1813 builtin_asm_get_stackframeinfo(){
1814 /*log_text("builtin_asm_get_stackframeinfo()");*/
1815 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1816 #ifdef HAVE___THREAD
1817         return &_thread_nativestackframeinfo; /*support for __thread attribute*/
1818 #else
1819     return &((nativethread*) pthread_getspecific(tkey_stackframeinfo))->_stackframeinfo /*copied from exception handling, is that really */
1820         /*old pthread*/
1821 #endif
1822 #else
1823 #warning FIXME FOR OLD THREAD IMPL (jowenn)
1824         return &_thread_nativestackframeinfo; /* no threading, at least no native*/
1825 #endif
1826 }
1827
1828 /*
1829  * These are local overrides for various environment variables in Emacs.
1830  * Please do not remove this and leave it at the end of the file, where
1831  * Emacs will automagically detect them.
1832  * ---------------------------------------------------------------------
1833  * Local variables:
1834  * mode: c
1835  * indent-tabs-mode: t
1836  * c-basic-offset: 4
1837  * tab-width: 4
1838  * End:
1839  */